Esper version 8.2.0 handles JSON documents directly, without the need to create a class. It does so by supporting EPL create-schema for JSON, with the EPL compiler producing a suitable streaming JSON parser and a value class with fields that hold parsed JSON values. This blog post compares the performance of Gson and Jackson with the JSON parser that the EPL compiler produces.
The tests run the java-json-benchmark which we extended to test Esper. For reference, Gson is a JSON serialization/deserialization library and so is Jackson.
The JSON string contains multiple user information such as user id (guid), age, eye color, address as well as user tags and friend information. The string is ~1k bytes in size.
{ "users": [ { "_id": "45166552176594981065", "index": 692815193, "guid": "oLzFhQttjjCGmijYulZg", "isActive": true, "balance": "XtMtTkSfmQtyRHS1086c", "picture": "Q8YoyJ0cL1MGFwC9bpAzQXSFBEcAUQ8lGQekvJZDeJ5C5p", "age": 23, "eyeColor": "XqoN9IzOBVixZhrofJpd", "name": "xBavaMCv6j0eYkT6HMcB", "gender": "VnuP3BaA3flaA6dLGvqO", "company": "L9yT2IsGTjOgQc0prb4r", "email": "rfmlFaVxGBSZFybTIKz0", "phone": "vZsxzv8DlzimJauTSBre", "address": "fZgFDv9tX1oonnVjcNVv", "about": "WysqSAN1psGsJBCFSR7P", "registered": "Lsw4RK5gtyNWGYp9dDhy", "latitude": 2.6395313895198393, "longitude": 110.5363758848371, "tags": [ "Hx6qJTHe8y", "23vYh8ILj6", "geU64sSQgH", "ezNI8Gx5vq" ], "friends": [ { "id": "3987", "name": "dWwKYheGgTZejIMYdglXvvrWAzUqsk" }, { "id": "4673", "name": "EqVIiZyuhSCkWXvqSxgyQihZaiwSra" } ], "greeting": "xfS8vUXYq4wzufBLP6CY", "favoriteFruit": "KT0tVAxXRawtbeQIWAot" }, { "_id": "23504426278646846580", "index": 675066974, "guid": "MfiCc1n1WfG6d6iXcdNf", "isActive": true, "balance": "OQEwTOBvwK0b8dJYFpBU", "picture": "avtMGQxSrO1h86V7KVaKaWUFZ0ooZd9GmIynRomjCjP8tEN", "age": 33, "eyeColor": "Fjsm1nmwyphAw7DRnfZ7", "name": "NnjrrCj1TTObhT9gHMH2", "gender": "ISVVoyQ4cbEjQVoFy5z0", "company": "AfcGdkzUQMzg69yjvmL5", "email": "mXLtlNEJjw5heFiYykwV", "phone": "zXbn9iJ5ljRHForNOa79", "address": "XXQUcaDIX2qpyZKtw8zl", "about": "GBVYHdxZYgGCey6yogEi", "registered": "bTJynDeyvZRbsYQIW9ys", "latitude": 16.675958191062414, "longitude": 114.20858157883556, "tags": [], "friends": [], "greeting": "EQqKZyiGnlyHeZf9ojnl", "favoriteFruit": "9aUx0u6G840i0EeKFM4Z" } ] }
Listed below is the EPL schema for the JSON document.
create json schema Friend(id string, name string);
create json schema User(_id string,
index
int,
guid string,
isActive string,
balance string,
picture string,
age int,
eyeColor string,
name string,
gender string,
company string,
email string,
phone string,
address string,
about string,
registered string,
latitude double,
longitude double,
tags string[],
friends Friend[],
greeting string,
favoriteFruit string);
create json schema Users(users User[]);
The benchmark compiles and deploys the EPL. It obtains the event sender to parse JSON without actually processing the event. The steps for this are in the next few line.
compileDeploy(runtime, schema); // compile and deploy schema (see doc) EventSenderJson sender = (EventSenderJson) runtime.getEventService().getEventSender("Users"); sender.parse(json); // json string as above
We extended the java-json-benchmark project to run Esper. The java-json-benchmark uses JMH and can run the different libraries. The results of the run is below.
.\run.ps1 deser --apis databind --libs "esper,gson,jackson" Benchmark Mode Cnt Score Error Units Deserialization.gson thrpt 20 380355.156 ± 102952.861 ops/s Deserialization.esper thrpt 20 625104.578 ± 124892.697 ops/s Deserialization.jackson thrpt 20 703692.069 ± 166341.185 ops/s
It is not clear why Gson performance looks low. The complete output is below.
Run progress: 0.00% complete, ETA 00:01:10 Fork: 1 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 356831.878 ops/s Warmup Iteration 2: 486136.353 ops/s Warmup Iteration 3: 515357.952 ops/s Warmup Iteration 4: 509446.072 ops/s Warmup Iteration 5: 518303.540 ops/s Iteration 1: 517984.589 ops/s Iteration 2: 518057.298 ops/s Iteration 3: 517874.770 ops/s Iteration 4: 520368.313 ops/s Iteration 5: 504031.483 ops/s Iteration 6: 259520.276 ops/s Iteration 7: 141100.628 ops/s Iteration 8: 196268.361 ops/s Iteration 9: 228216.651 ops/s Iteration 10: 260322.078 ops/s Run progress: 50.00% complete, ETA 00:00:39 Fork: 2 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 193367.787 ops/s Warmup Iteration 2: 280659.932 ops/s Warmup Iteration 3: 302554.536 ops/s Warmup Iteration 4: 322162.441 ops/s Warmup Iteration 5: 329478.408 ops/s Iteration 1: 341587.662 ops/s Iteration 2: 353809.794 ops/s Iteration 3: 364638.181 ops/s Iteration 4: 384033.414 ops/s Iteration 5: 402530.792 ops/s Iteration 6: 412963.221 ops/s Iteration 7: 423726.426 ops/s Iteration 8: 431531.785 ops/s Iteration 9: 440825.460 ops/s Iteration 10: 448492.988 ops/s Result "com.github.fabienrenaud.jjb.databind.Deserialization.gson": 383394.208 ±(99.9%) 99933.179 ops/s [Average] (min, avg, max) = (141100.628, 383394.208, 520368.313), stdev = 115083.198 CI (99.9%): [283461.029, 483327.387] (assumes normal distribution) Run complete. Total time: 00:01:19 Benchmark Mode Cnt Score Error Units Deserialization.gson thrpt 20 383394.208 ± 99933.179 ops/s java -server -XX:+AggressiveOpts -Xms2g -Xmx2g -jar build\libs\app.jar deser --apis databind --libs esper,gson,jackson JMH version: 1.20 VM version: JDK 1.8.0_192, VM 25.192-b12 VM invoker: C:\Java\jdk1.8.0_192\jre\bin\java.exe VM options: Warmup: 5 iterations, 1 s each Measurement: 10 iterations, 3 s each Timeout: 10 min per iteration Threads: 16 threads, will synchronize iterations Benchmark mode: Throughput, ops/time Benchmark: com.github.fabienrenaud.jjb.databind.Deserialization.gson Run progress: 0.00% complete, ETA 00:03:30 Fork: 1 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 288279.935 ops/s Warmup Iteration 2: 489983.172 ops/s Warmup Iteration 3: 520986.946 ops/s Warmup Iteration 4: 524690.847 ops/s Warmup Iteration 5: 524284.236 ops/s Iteration 1: 526489.947 ops/s Iteration 2: 525270.990 ops/s Iteration 3: 526443.131 ops/s Iteration 4: 513476.515 ops/s Iteration 5: 153916.529 ops/s Iteration 6: 168760.049 ops/s Iteration 7: 210875.579 ops/s Iteration 8: 237990.523 ops/s Iteration 9: 273769.762 ops/s Iteration 10: 298343.511 ops/s Run progress: 16.67% complete, ETA 00:03:15 Fork: 2 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 197768.475 ops/s Warmup Iteration 2: 306685.739 ops/s Warmup Iteration 3: 337464.437 ops/s Warmup Iteration 4: 347067.561 ops/s Warmup Iteration 5: 350076.319 ops/s Iteration 1: 364416.146 ops/s Iteration 2: 381411.513 ops/s Iteration 3: 396296.144 ops/s Iteration 4: 406238.196 ops/s Iteration 5: 408165.895 ops/s Iteration 6: 422488.775 ops/s Iteration 7: 433276.809 ops/s Iteration 8: 445738.057 ops/s Iteration 9: 453633.056 ops/s Iteration 10: 460101.988 ops/s Result "com.github.fabienrenaud.jjb.databind.Deserialization.gson": 380355.156 ±(99.9%) 102952.861 ops/s [Average] (min, avg, max) = (153916.529, 380355.156, 526489.947), stdev = 118560.668 CI (99.9%): [277402.295, 483308.017] (assumes normal distribution) JMH version: 1.20 VM version: JDK 1.8.0_192, VM 25.192-b12 VM invoker: C:\Java\jdk1.8.0_192\jre\bin\java.exe VM options: Warmup: 5 iterations, 1 s each Measurement: 10 iterations, 3 s each Timeout: 10 min per iteration Threads: 16 threads, will synchronize iterations Benchmark mode: Throughput, ops/time Benchmark: com.github.fabienrenaud.jjb.databind.Deserialization.jackson Run progress: 33.33% complete, ETA 00:02:37 Fork: 1 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 474878.945 ops/s Warmup Iteration 2: 802966.481 ops/s Warmup Iteration 3: 712858.027 ops/s Warmup Iteration 4: 740797.359 ops/s Warmup Iteration 5: 763551.499 ops/s Iteration 1: 782842.724 ops/s Iteration 2: 886217.925 ops/s Iteration 3: 897024.236 ops/s Iteration 4: 906403.846 ops/s Iteration 5: 922395.550 ops/s Iteration 6: 885245.860 ops/s Iteration 7: 826431.459 ops/s Iteration 8: 844156.887 ops/s Iteration 9: 854776.515 ops/s Iteration 10: 870187.841 ops/s Run progress: 50.00% complete, ETA 00:01:57 Fork: 2 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 546879.887 ops/s Warmup Iteration 2: 849142.467 ops/s Warmup Iteration 3: 335546.405 ops/s Warmup Iteration 4: 232004.319 ops/s Warmup Iteration 5: 236806.194 ops/s Iteration 1: 304245.449 ops/s Iteration 2: 398422.848 ops/s Iteration 3: 448193.203 ops/s Iteration 4: 503593.337 ops/s Iteration 5: 539268.939 ops/s Iteration 6: 581295.972 ops/s Iteration 7: 616766.077 ops/s Iteration 8: 640036.098 ops/s Iteration 9: 667639.232 ops/s Iteration 10: 698697.385 ops/s Result "com.github.fabienrenaud.jjb.databind.Deserialization.jackson": 703692.069 ±(99.9%) 166341.185 ops/s [Average] (min, avg, max) = (304245.449, 703692.069, 922395.550), stdev = 191558.755 CI (99.9%): [537350.885, 870033.254] (assumes normal distribution) JMH version: 1.20 VM version: JDK 1.8.0_192, VM 25.192-b12 VM invoker: C:\Java\jdk1.8.0_192\jre\bin\java.exe VM options: Warmup: 5 iterations, 1 s each Measurement: 10 iterations, 3 s each Timeout: 10 min per iteration Threads: 16 threads, will synchronize iterations Benchmark mode: Throughput, ops/time Benchmark: com.github.fabienrenaud.jjb.databind.Deserialization.jackson_afterburner Run progress: 66.67% complete, ETA 00:01:18 Fork: 1 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 577052.249 ops/s Warmup Iteration 2: 837639.921 ops/s Warmup Iteration 3: 851474.733 ops/s Warmup Iteration 4: 873343.762 ops/s Warmup Iteration 5: 873135.520 ops/s Iteration 1: 889379.290 ops/s Iteration 2: 914258.396 ops/s Iteration 3: 928132.585 ops/s Iteration 4: 953161.613 ops/s Iteration 5: 952915.538 ops/s Iteration 6: 958374.194 ops/s Iteration 7: 977448.096 ops/s Iteration 8: 1009370.292 ops/s Iteration 9: 1025722.026 ops/s Iteration 10: 1037452.536 ops/s Run progress: 83.33% complete, ETA 00:00:39 Fork: 2 of 2 Warmup Iteration 1: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Using SEED=355928074 as seed for Random 712829.114 ops/s Warmup Iteration 2: 1070309.076 ops/s Warmup Iteration 3: 1027631.655 ops/s Warmup Iteration 4: 905102.951 ops/s Warmup Iteration 5: 923147.446 ops/s Iteration 1: 942076.760 ops/s Iteration 2: 945732.126 ops/s Iteration 3: 955351.526 ops/s Iteration 4: 973549.500 ops/s Iteration 5: 999500.944 ops/s Iteration 6: 1020378.209 ops/s Iteration 7: 1024975.429 ops/s Iteration 8: 1030572.193 ops/s Iteration 9: 1052722.004 ops/s Iteration 10: 996312.536 ops/s Result "com.github.fabienrenaud.jjb.databind.Deserialization.jackson_afterburner": 979369.290 ±(99.9%) 39243.509 ops/s [Average] (min, avg, max) = (889379.290, 979369.290, 1052722.004), stdev = 45192.883 CI (99.9%): [940125.781, 1018612.799] (assumes normal distribution) Run complete. Total time: 00:03:55 Benchmark Mode Cnt Score Error Units Deserialization.gson thrpt 20 380355.156 ± 102952.861 ops/s Deserialization.esper thrpt 20 625104.578 ± 124892.697 ops/s Deserialization.jackson thrpt 20 703692.069 ± 166341.185 ops/s Deserialization.jackson_afterburner thrpt 20 979369.290 ± 39243.509 ops/s