以下記事に続いて、Gson
, Genson
, Fastjson
, JSONIC
のベンチマークをJMHを用いて取得しました。
JSONの項目数が1, 2, 4, 8個の場合のそれぞれについて以下操作を実施して測定してみました
- Javaオブジェクト⇒JSON文字列の変換(Serialize)
- JSON文字列⇒Javaオブジェクトの変換(Deserialize)
pom.xmlに追加した内容は以下の通りです
(Lombokの@Data
アノテーションを利用してコード省略をするため、Lombokのライブラリも組み込んでいます)
<dependency> <groupId>com.owlike</groupId> <artifactId>genson</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.7</version> </dependency> <dependency> <groupId>net.arnx</groupId> <artifactId>jsonic</artifactId> <version>1.3.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> <scope>provided</scope> </dependency>
■変換対象のJavaオブジェクト
- メンバが1個
import lombok.Data; @Data public class Param1 { /** * JSON文字列 * * { * "data1": "abcde" * } */ public static final String JSON_STR = "{\"data1\":\"abcde\"}"; public static final Param1 INSTANCE = new Param1(); static { INSTANCE.setData1("012345"); } private String data1; }
- メンバが2個
import lombok.Data; @Data public class Param2 { /** * JSON文字列 * * { * "data1": "abcde", * "data2": "fghij" * } */ public static final String JSON_STR = "{\"data1\":\"abcde\", \"data2\":\"fghij\"}"; public static final Param2 INSTANCE = new Param2(); static { INSTANCE.setData1("12345"); INSTANCE.setData2("67890"); } private String data1; private String data2; }
- メンバが4個
import lombok.Data; @Data public class Param4 { /** * JSON文字列 * * { * "data1": "abcde", * "data2": "fghij", * "data3": "klmno", * "data4": "pqrst" * } */ public static final String JSON_STR = "{\"data1\":\"abcde\", \"data2\":\"fghij\", \"data3\":\"klmno\", \"data4\":\"pqrst\"}"; public static final Param4 INSTANCE = new Param4(); static { INSTANCE.setData1("12345"); INSTANCE.setData2("67890"); INSTANCE.setData3("54321"); INSTANCE.setData4("09876"); } private String data1; private String data2; private String data3; private String data4; }
- メンバが8個
import lombok.Data; @Data public class Param8 { /** * JSON文字列 * * { * "data1": "abcde", * "data2": "fghij", * "data3": "klmno", * "data4": "pqrst", * "data5": "0bcde", * "data6": "1ghij", * "data7": "2lmno", * "data8": "3qrst" * } */ public static final String JSON_STR = "{\"data1\":\"abcde\", \"data2\":\"fghij\", \"data3\":\"klmno\", \"data4\":\"pqrst\", \"data5\":\"0bcde\", \"data6\":\"1ghij\", \"data7\":\"2lmno\", \"data8\":\"3qrst\"}"; public static final Param8 INSTANCE = new Param8(); static { INSTANCE.setData1("12345"); INSTANCE.setData2("67890"); INSTANCE.setData3("54321"); INSTANCE.setData4("09876"); INSTANCE.setData5("12344"); INSTANCE.setData6("67899"); INSTANCE.setData7("44321"); INSTANCE.setData8("99876"); } private String data1; private String data2; private String data3; private String data4; private String data5; private String data6; private String data7; private String data8; }
■ベンチマーク取得用のコード
import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import com.google.gson.Gson; import com.owlike.genson.Genson; public class JsonBenchmark { static final Genson genson = new Genson(); static final Gson gson = new Gson(); @Benchmark public void Gson_Param1_Deserialize() { Param1 obj = gson.fromJson(Param1.JSON_STR, Param1.class); } @Benchmark public void Genson_Param1_Deserialize() { Param1 obj = genson.deserialize(Param1.JSON_STR, Param1.class); } @Benchmark public void JSONIC_Param1_Deserialize() { Param1 obj = net.arnx.jsonic.JSON.decode(Param1.JSON_STR, Param1.class); } @Benchmark public void FastJson_Param1_Deserialize() { Param1 obj = com.alibaba.fastjson.JSON.parseObject(Param1.JSON_STR, Param1.class); } @Benchmark public void Gson_Param1_Serialize() { String json = gson.toJson(Param1.INSTANCE); } @Benchmark public void Genson_Param1_Serialize() { String json = genson.serialize(Param1.INSTANCE); } @Benchmark public void JSONIC_Param1_Serialize() { String json = net.arnx.jsonic.JSON.encode(Param1.INSTANCE); } @Benchmark public void FastJson_Param1_Serialize() { String json = com.alibaba.fastjson.JSON.toJSONString(Param1.INSTANCE); } /* --------------------------------------------------------------------- */ @Benchmark public void Gson_Param2_Deserialize() { Param2 obj = gson.fromJson(Param2.JSON_STR, Param2.class); } @Benchmark public void Genson_Param2_Deserialize() { Param2 obj = genson.deserialize(Param2.JSON_STR, Param2.class); } @Benchmark public void JSONIC_Param2_Deserialize() { Param2 obj = net.arnx.jsonic.JSON.decode(Param2.JSON_STR, Param2.class); } @Benchmark public void FastJson_Param2_Deserialize() { Param2 obj = com.alibaba.fastjson.JSON.parseObject(Param2.JSON_STR, Param2.class); } @Benchmark public void Gson_Param2_Serialize() { String json = gson.toJson(Param2.INSTANCE); } @Benchmark public void Genson_Param2_Serialize() { String json = genson.serialize(Param2.INSTANCE); } @Benchmark public void JSONIC_Param2_Serialize() { String json = net.arnx.jsonic.JSON.encode(Param2.INSTANCE); } @Benchmark public void FastJson_Param2_Serialize() { String json = com.alibaba.fastjson.JSON.toJSONString(Param2.INSTANCE); } /* --------------------------------------------------------------------- */ @Benchmark public void Gson_Param4_Deserialize() { Param4 obj = gson.fromJson(Param4.JSON_STR, Param4.class); } @Benchmark public void Genson_Param4_Deserialize() { Param4 obj = genson.deserialize(Param4.JSON_STR, Param4.class); } @Benchmark public void JSONIC_Param4_Deserialize() { Param4 obj = net.arnx.jsonic.JSON.decode(Param4.JSON_STR, Param4.class); } @Benchmark public void FastJson_Param4_Deserialize() { Param4 obj = com.alibaba.fastjson.JSON.parseObject(Param4.JSON_STR, Param4.class); } @Benchmark public void Gson_Param4_Serialize() { String json = gson.toJson(Param4.INSTANCE); } @Benchmark public void Genson_Param4_Serialize() { String json = genson.serialize(Param4.INSTANCE); } @Benchmark public void JSONIC_Param4_Serialize() { String json = net.arnx.jsonic.JSON.encode(Param4.INSTANCE); } @Benchmark public void FastJson_Param4_Serialize() { String json = com.alibaba.fastjson.JSON.toJSONString(Param4.INSTANCE); } /* --------------------------------------------------------------------- */ @Benchmark public void Gson_Param8_Deserialize() { Param8 obj = gson.fromJson(Param8.JSON_STR, Param8.class); } @Benchmark public void Genson_Param8_Deserialize() { Param8 obj = genson.deserialize(Param8.JSON_STR, Param8.class); } @Benchmark public void JSONIC_Param8_Deserialize() { Param8 obj = net.arnx.jsonic.JSON.decode(Param8.JSON_STR, Param8.class); } @Benchmark public void FastJson_Param8_Deserialize() { Param8 obj = com.alibaba.fastjson.JSON.parseObject(Param8.JSON_STR, Param8.class); } @Benchmark public void Gson_Param8_Serialize() { String json = gson.toJson(Param8.INSTANCE); } @Benchmark public void Genson_Param8_Serialize() { String json = genson.serialize(Param8.INSTANCE); } @Benchmark public void JSONIC_Param8_Serialize() { String json = net.arnx.jsonic.JSON.encode(Param8.INSTANCE); } @Benchmark public void FastJson_Param8_Serialize() { String json = com.alibaba.fastjson.JSON.toJSONString(Param8.INSTANCE); } /* --------------------------------------------------------------------- */ public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() .include(JsonBenchmark.class.getSimpleName()) .warmupIterations(15) .forks(1) .mode(Mode.Throughput) .build(); new Runner(opt).run(); } }
■実行結果
Benchmark Mode Cnt Score Error Units JsonBenchmark.FastJson_Param1_Deserialize thrpt 20 4195673.493 ± 19574.347 ops/s JsonBenchmark.FastJson_Param1_Serialize thrpt 20 3449799.211 ± 33319.993 ops/s JsonBenchmark.FastJson_Param2_Deserialize thrpt 20 1321092.272 ± 10055.516 ops/s JsonBenchmark.FastJson_Param2_Serialize thrpt 20 2472298.598 ± 249420.632 ops/s JsonBenchmark.FastJson_Param4_Deserialize thrpt 20 589985.238 ± 31710.681 ops/s JsonBenchmark.FastJson_Param4_Serialize thrpt 20 1756121.681 ± 37347.932 ops/s JsonBenchmark.FastJson_Param8_Deserialize thrpt 20 295910.818 ± 3115.337 ops/s JsonBenchmark.FastJson_Param8_Serialize thrpt 20 1121379.655 ± 19931.463 ops/s JsonBenchmark.Genson_Param1_Deserialize thrpt 20 472028.167 ± 43954.179 ops/s JsonBenchmark.Genson_Param1_Serialize thrpt 20 789158.670 ± 14181.205 ops/s JsonBenchmark.Genson_Param2_Deserialize thrpt 20 449204.789 ± 14293.770 ops/s JsonBenchmark.Genson_Param2_Serialize thrpt 20 679484.606 ± 37354.086 ops/s JsonBenchmark.Genson_Param4_Deserialize thrpt 20 305384.858 ± 30222.529 ops/s JsonBenchmark.Genson_Param4_Serialize thrpt 20 515371.617 ± 27980.245 ops/s JsonBenchmark.Genson_Param8_Deserialize thrpt 20 245868.402 ± 24096.430 ops/s JsonBenchmark.Genson_Param8_Serialize thrpt 20 350953.967 ± 25198.046 ops/s JsonBenchmark.Gson_Param1_Deserialize thrpt 20 618404.934 ± 40876.569 ops/s JsonBenchmark.Gson_Param1_Serialize thrpt 20 1295734.021 ± 65292.606 ops/s JsonBenchmark.Gson_Param2_Deserialize thrpt 20 415526.341 ± 46925.218 ops/s JsonBenchmark.Gson_Param2_Serialize thrpt 20 896601.209 ± 8078.346 ops/s JsonBenchmark.Gson_Param4_Deserialize thrpt 20 356610.773 ± 27809.496 ops/s JsonBenchmark.Gson_Param4_Serialize thrpt 20 523139.719 ± 3893.311 ops/s JsonBenchmark.Gson_Param8_Deserialize thrpt 20 231396.047 ± 7577.424 ops/s JsonBenchmark.Gson_Param8_Serialize thrpt 20 270730.003 ± 4979.947 ops/s JsonBenchmark.JSONIC_Param1_Deserialize thrpt 20 78736.888 ± 2090.946 ops/s JsonBenchmark.JSONIC_Param1_Serialize thrpt 20 125495.921 ± 12245.697 ops/s JsonBenchmark.JSONIC_Param2_Deserialize thrpt 20 73901.511 ± 1970.644 ops/s JsonBenchmark.JSONIC_Param2_Serialize thrpt 20 126911.843 ± 740.589 ops/s JsonBenchmark.JSONIC_Param4_Deserialize thrpt 20 65997.762 ± 696.490 ops/s JsonBenchmark.JSONIC_Param4_Serialize thrpt 20 107243.447 ± 793.303 ops/s JsonBenchmark.JSONIC_Param8_Deserialize thrpt 20 48507.646 ± 2978.033 ops/s JsonBenchmark.JSONIC_Param8_Serialize thrpt 20 88963.475 ± 755.584 ops/s
Scoreの値を表にまとめてみました。
Serialize/Deserialize | ライブラリ | 項目1個 | 項目2個 | 項目4個 | 項目8個 |
---|---|---|---|---|---|
Bean⇒JSON (Serialize) | Fastjson | 3449799.211 | 2472298.598 | 1756121.681 | 1121379.655 |
Genson | 789158.670 | 679484.606 | 515371.617 | 350953.967 | |
Gson | 1295734.021 | 896601.209 | 523139.719 | 270730.003 | |
JSONIC | 125495.921 | 126911.843 | 107243.447 | 88963.475 | |
JSON⇒Bean (Deserialize) | Fastjson | 4195673.493 | 1321092.272 | 589985.238 | 295910.818 |
Genson | 472028.167 | 449204.789 | 305384.858 | 245868.402 | |
Gson | 618404.934 | 415526.341 | 356610.773 | 231396.047 | |
JSONIC | 78736.888 | 73901.511 | 65997.762 | 48507.646 |
JSONの項目数で比較してみると、基本的に項目数が増えるごとにScoreが減少していてそれだけ時間を要することが分かります。
ライブラリごとの結果を比較してみると、JSONICの遅さとFastjsonの速さが目につきます。
項目8個の場合のDeserializeでは、Fastjson, Genson, Gsonでの性能差はあまり無いという結果になっています。