4. 性能压测

4.1. 测试环境

CPU : Intel Core i5-7500 3.4GHz 3.4GHz
Momey : 16GB
OS : WINDOWS 10
JAVA IDE : Eclipse 2018-12

4.2. 测试案例

压测对象:okjson v0.0.8.0、fastjson v1.2.56。

压测JSON解析器性能。JSON文本数据映射到实体类各属性里去,交替各压5轮,每轮100万次。

压测JSON生成器性能。由实体类生成JSON文本,交替各压5轮,每轮200万次。

JSON文件press.json

  1. {
  2. "str1" : "str1" ,
  3. "int1" : 1234 ,
  4. "double1" : 1.234 ,
  5. "boolean1" : true ,
  6. "press2" : {
  7. "byte2" : 2 ,
  8. "short2" : 23 ,
  9. "long2" : 23456789 ,
  10. "float2" : 2.345
  11. }
  12. }

实体类PressDataClass.java

  1. package xyz.calvinwilliams.test_jsonparser;
  2. public class PressDataClass {
  3. private String str1 ;
  4. private int int1 ;
  5. private Double double1 ;
  6. private boolean boolean1 ;
  7. private String null1 ;
  8. public PressDataClass2 press2 ;
  9. public String getStr1() {
  10. return str1;
  11. }
  12. public void setStr1(String str1) {
  13. this.str1 = str1;
  14. }
  15. public int getInt1() {
  16. return int1;
  17. }
  18. public void setInt1(int int1) {
  19. this.int1 = int1;
  20. }
  21. public Double getDouble1() {
  22. return double1;
  23. }
  24. public void setDouble1(Double double1) {
  25. this.double1 = double1;
  26. }
  27. public boolean isBoolean1() {
  28. return boolean1;
  29. }
  30. public void setBoolean1(boolean boolean1) {
  31. this.boolean1 = boolean1;
  32. }
  33. public PressDataClass2 getPress2() {
  34. return press2;
  35. }
  36. public void setPress2(PressDataClass2 press2) {
  37. this.press2 = press2;
  38. }
  39. public String getNull1() {
  40. return null1;
  41. }
  42. public void setNull1(String null1) {
  43. this.null1 = null1;
  44. }
  45. }

实体类PressDataClass2.java

  1. package xyz.calvinwilliams.test_jsonparser;
  2. public class PressDataClass2 {
  3. private byte byte2 ;
  4. private short short2 ;
  5. private Long long2 ;
  6. private float float2 ;
  7. public byte getByte2() {
  8. return byte2;
  9. }
  10. public void setByte2(byte byte2) {
  11. this.byte2 = byte2;
  12. }
  13. public short getShort2() {
  14. return short2;
  15. }
  16. public void setShort2(short short2) {
  17. this.short2 = short2;
  18. }
  19. public Long getLong2() {
  20. return long2;
  21. }
  22. public void setLong2(Long long2) {
  23. this.long2 = long2;
  24. }
  25. public float getFloat2() {
  26. return float2;
  27. }
  28. public void setFloat2(float float2) {
  29. this.float2 = float2;
  30. }
  31. }

4.3. fastjson压测代码

fastjson解析器压测代码PressFastJsonParser.java

  1. package xyz.calvinwilliams.test_jsonparser;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import com.alibaba.fastjson.*;
  5. public class PressFastJsonParser {
  6. public static void main(String[] args) {
  7. File file = new File( "press.json" ) ;
  8. Long fileSize = file.length() ;
  9. byte[] json = new byte[fileSize.intValue()] ;
  10. try {
  11. FileInputStream in = new FileInputStream(file);
  12. in.read(json);
  13. in.close();
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. return;
  17. }
  18. String jsonString = new String(json) ;
  19. long l , count = 1000000 ;
  20. long beginMillisSecondstamp = System.currentTimeMillis() ;
  21. for( l = 0 ; l < count ; l++ ) {
  22. PressDataClass obj = JSON.parseObject(jsonString, new TypeReference<PressDataClass>() {}) ;
  23. if( obj == null ) {
  24. System.out.println( "JSON.stringToObject failed" );
  25. return;
  26. }
  27. else if( l == 0 ){
  28. System.out.println( "JSON.stringToObject ok" );
  29. System.out.println( "------------------------------ dump PressDataClass" );
  30. System.out.println( "DataClass.str1["+obj.getStr1()+"]" );
  31. System.out.println( "PressDataClass.int1["+obj.getInt1()+"]" );
  32. System.out.println( "PressDataClass.Double1["+obj.getDouble1()+"]" );
  33. System.out.println( "PressDataClass.boolean1["+obj.isBoolean1()+"]" );
  34. System.out.println( "------------------------------ dump PressDataClass.press2" );
  35. if( obj.press2 != null ) {
  36. System.out.println( "PressDataClass.branch2.byte2["+obj.press2.getByte2()+"]" );
  37. System.out.println( "PressDataClass.branch2.short2["+obj.press2.getShort2()+"]" );
  38. System.out.println( "PressDataClass.branch2.Long2["+obj.press2.getLong2()+"]" );
  39. System.out.println( "PressDataClass.branch2.float2["+obj.press2.getFloat2()+"]" );
  40. }
  41. }
  42. }
  43. long endMillisSecondstamp = System.currentTimeMillis() ;
  44. double elpaseSecond = (endMillisSecondstamp-beginMillisSecondstamp)/1000.0 ;
  45. System.out.println( "count["+count+"] elapse["+elpaseSecond+"]s" );
  46. double countPerSecond = count / elpaseSecond ;
  47. System.out.println( "count per second["+countPerSecond+"]" );
  48. return;
  49. }
  50. }

fastjson生成器压测代码PressFastJsonGenerator.java

  1. package xyz.calvinwilliams.test_jsonparser;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import com.alibaba.fastjson.*;
  5. public class PressFastJsonGenerator {
  6. public static void main(String[] args) {
  7. PressDataClass object = new PressDataClass() ;
  8. object.setStr1("str1");
  9. object.setInt1(1234);
  10. object.setDouble1(1.234);
  11. object.setBoolean1(true);
  12. object.setNull1(null);
  13. object.press2 = new PressDataClass2() ;
  14. object.press2.setByte2((byte)2);
  15. object.press2.setShort2((short)23);
  16. object.press2.setLong2(23456789L);
  17. object.press2.setFloat2(2.345f);
  18. System.out.println( "------------------------------ dump PressDataClass" );
  19. System.out.println( "DataClass.str1["+object.getStr1()+"]" );
  20. System.out.println( "PressDataClass.int1["+object.getInt1()+"]" );
  21. System.out.println( "PressDataClass.Double1["+object.getDouble1()+"]" );
  22. System.out.println( "PressDataClass.boolean1["+object.isBoolean1()+"]" );
  23. System.out.println( "PressDataClass.null1["+object.getNull1()+"]" );
  24. System.out.println( "------------------------------ dump PressDataClass.press2" );
  25. if( object.press2 != null ) {
  26. System.out.println( "PressDataClass.branch2.byte2["+object.press2.getByte2()+"]" );
  27. System.out.println( "PressDataClass.branch2.short2["+object.press2.getShort2()+"]" );
  28. System.out.println( "PressDataClass.branch2.Long2["+object.press2.getLong2()+"]" );
  29. System.out.println( "PressDataClass.branch2.float2["+object.press2.getFloat2()+"]" );
  30. }
  31. long l , count = 5000000 ;
  32. long beginMillisSecondstamp = System.currentTimeMillis() ;
  33. for( l = 0 ; l < count ; l++ ) {
  34. String jsonString = JSON.toJSONString( object ) ;
  35. if( jsonString == null ) {
  36. System.out.println( "JSON.toJSONString failed" );
  37. return;
  38. }
  39. else if( l == count-1 ){
  40. System.out.println( "JSON.toJSONString ok" );
  41. System.out.println( jsonString );
  42. }
  43. }
  44. long endMillisSecondstamp = System.currentTimeMillis() ;
  45. double elpaseSecond = (endMillisSecondstamp-beginMillisSecondstamp)/1000.0 ;
  46. System.out.println( "count["+count+"] elapse["+elpaseSecond+"]s" );
  47. double countPerSecond = count / elpaseSecond ;
  48. System.out.println( "count per second["+countPerSecond+"]" );
  49. return;
  50. }
  51. }

4.4. okjson压测代码

okjson解析器压测代码PressOkJsonParser.java

  1. package xyz.calvinwilliams.test_jsonparser;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import xyz.calvinwilliams.okjson.*;
  5. import xyz.calvinwilliams.test_jsonparser.PressDataClass;
  6. public class PressOkJsonParser {
  7. public static void main(String[] args) {
  8. File file = new File( "press.json" ) ;
  9. Long fileSize = file.length() ;
  10. byte[] json = new byte[fileSize.intValue()] ;
  11. try {
  12. FileInputStream in = new FileInputStream(file);
  13. in.read(json);
  14. in.close();
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. return;
  18. }
  19. String jsonString = new String(json) ;
  20. long l , count = 1000000 ;
  21. long beginMillisSecondstamp = System.currentTimeMillis() ;
  22. for( l = 0 ; l < count ; l++ ) {
  23. PressDataClass object = OKJSON.stringToObject( jsonString, PressDataClass.class, OKJSON.OPTIONS_DIRECT_ACCESS_PROPERTY_ENABLE ) ;
  24. if( object == null ) {
  25. System.out.println( "okjson.stringToObject failed["+OKJSON.getErrorCode()+"]" );
  26. return;
  27. } else if( l == 0 ){
  28. System.out.println( "okjson.stringToObject ok" );
  29. System.out.println( "------------------------------ dump PressDataClass" );
  30. System.out.println( "DataClass.str1["+object.getStr1()+"]" );
  31. System.out.println( "PressDataClass.int1["+object.getInt1()+"]" );
  32. System.out.println( "PressDataClass.Double1["+object.getDouble1()+"]" );
  33. System.out.println( "PressDataClass.boolean1["+object.isBoolean1()+"]" );
  34. System.out.println( "------------------------------ dump PressDataClass.press2" );
  35. if( object.press2 != null ) {
  36. System.out.println( "PressDataClass.branch2.byte2["+object.press2.getByte2()+"]" );
  37. System.out.println( "PressDataClass.branch2.short2["+object.press2.getShort2()+"]" );
  38. System.out.println( "PressDataClass.branch2.Long2["+object.press2.getLong2()+"]" );
  39. System.out.println( "PressDataClass.branch2.float2["+object.press2.getFloat2()+"]" );
  40. }
  41. }
  42. }
  43. long endMillisSecondstamp = System.currentTimeMillis() ;
  44. double elpaseSecond = (endMillisSecondstamp-beginMillisSecondstamp)/1000.0 ;
  45. System.out.println( "count["+count+"] elapse["+elpaseSecond+"]s" );
  46. double countPerSecond = count / elpaseSecond ;
  47. System.out.println( "count per second["+countPerSecond+"]" );
  48. return;
  49. }
  50. }

okjson生成器压测代码PressOkJsonGenerator.java

  1. package xyz.calvinwilliams.test_jsonparser;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import xyz.calvinwilliams.okjson.OKJSON;
  5. import xyz.calvinwilliams.test_jsonparser.PressDataClass;
  6. public class PressOkJsonGenerator {
  7. public static void main(String[] args) {
  8. PressDataClass object = new PressDataClass() ;
  9. object.setStr1("str1");
  10. object.setInt1(1234);
  11. object.setDouble1(1.234);
  12. object.setBoolean1(true);
  13. object.setNull1(null);
  14. object.press2 = new PressDataClass2() ;
  15. object.press2.setByte2((byte)2);
  16. object.press2.setShort2((short)23);
  17. object.press2.setLong2(23456789L);
  18. object.press2.setFloat2(2.345f);
  19. System.out.println( "------------------------------ dump PressDataClass" );
  20. System.out.println( "DataClass.str1["+object.getStr1()+"]" );
  21. System.out.println( "PressDataClass.int1["+object.getInt1()+"]" );
  22. System.out.println( "PressDataClass.Double1["+object.getDouble1()+"]" );
  23. System.out.println( "PressDataClass.boolean1["+object.isBoolean1()+"]" );
  24. System.out.println( "PressDataClass.null1["+object.getNull1()+"]" );
  25. System.out.println( "------------------------------ dump PressDataClass.press2" );
  26. if( object.press2 != null ) {
  27. System.out.println( "PressDataClass.branch2.byte2["+object.press2.getByte2()+"]" );
  28. System.out.println( "PressDataClass.branch2.short2["+object.press2.getShort2()+"]" );
  29. System.out.println( "PressDataClass.branch2.Long2["+object.press2.getLong2()+"]" );
  30. System.out.println( "PressDataClass.branch2.float2["+object.press2.getFloat2()+"]" );
  31. }
  32. long l , count = 5000000 ;
  33. long beginMillisSecondstamp = System.currentTimeMillis() ;
  34. for( l = 0 ; l < count ; l++ ) {
  35. String jsonString = OKJSON.objectToString( object, 0 ) ;
  36. if( jsonString == null ) {
  37. System.out.println( "okjson.stringToObject failed["+OKJSON.getErrorCode()+"]["+OKJSON.getErrorDesc()+"]" );
  38. return;
  39. } else if( l == count-1 ){
  40. System.out.println( "okjson.stringToObject ok" );
  41. System.out.println( jsonString );
  42. }
  43. }
  44. long endMillisSecondstamp = System.currentTimeMillis() ;
  45. double elpaseSecond = (endMillisSecondstamp-beginMillisSecondstamp)/1000.0 ;
  46. System.out.println( "count["+count+"] elapse["+elpaseSecond+"]s" );
  47. double countPerSecond = count / elpaseSecond ;
  48. System.out.println( "count per second["+countPerSecond+"]" );
  49. return;
  50. }
  51. }

4.5. 测试过程

JSON解析器性能

okjson

  1. count[1000000] elapse[1.446]s
  2. count per second[691562.9322268326]

fastjson

  1. count[1000000] elapse[2.616]s
  2. count per second[382262.996941896]

okjson

  1. count[1000000] elapse[1.429]s
  2. count per second[699790.0629811056]

fastjson

  1. count[1000000] elapse[2.547]s
  2. count per second[392618.767177071]

okjson

  1. count[1000000] elapse[1.42]s
  2. count per second[704225.3521126761]

fastjson

  1. count[1000000] elapse[2.473]s
  2. count per second[404367.1653861707]

okjson

  1. count[1000000] elapse[1.432]s
  2. count per second[698324.0223463688]

fastjson

  1. count[1000000] elapse[2.48]s
  2. count per second[403225.8064516129]

okjson

  1. count[1000000] elapse[1.434]s
  2. count per second[697350.069735007]

fastjson

  1. count[1000000] elapse[2.459]s
  2. count per second[406669.37779585196]

JSON生成器性能

okjson

  1. count[2000000] elapse[1.399]s
  2. count per second[1429592.5661186562]

fastjson

  1. count[2000000] elapse[1.51]s
  2. count per second[1324503.311258278]

okjson

  1. count[2000000] elapse[1.347]s
  2. count per second[1484780.9948032666]

fastjson

  1. count[2000000] elapse[1.507]s
  2. count per second[1327140.0132714002]

okjson

  1. count[2000000] elapse[1.364]s
  2. count per second[1466275.6598240468]

fastjson

  1. count[2000000] elapse[1.403]s
  2. count per second[1425516.7498218103]

okjson

  1. count[2000000] elapse[1.363]s
  2. count per second[1467351.4306676448]

fastjson

  1. count[2000000] elapse[1.512]s
  2. count per second[1322751.3227513228]

okjson

  1. count[2000000] elapse[1.37]s
  2. count per second[1459854.01459854]

fastjson

  1. count[2000000] elapse[1.409]s
  2. count per second[1419446.4158978]

4.6. 测试结果

JSON解析器性能曲线图:

json_parsers_benchmark.png

JSON生成器性能曲线图:

json_generators_benchmark.png

说明:

  • 在JSON解析/反序列化处理性能上,okjson比fastjson快了近一倍(75%)。
  • 在JSON生成/序列化处理性能上,okjson比fastjson快了少许(7%)

其它说明:

  • fastjson静态类名为JSON取名不好,容易和其它JSON库冲突,或许温少就是这么霸气。okjson静态类名为OKJSON,比较低调 :)
  • 实体类中加了很多setter和getter是为了fastjson,okjson并不需要。okjson甚至连实体类构造方法都没有要求必须有,作为通用框架要兼容各种各样的场景。