Skip to content

Benchmarks ​

All benchmarks are reproducible and based on JMH (Java Microbenchmark Harness) or equivalent tools.

Accessor Performance Benchmark ​

SJF4J's OBNT relies on reflection for flexible access to POJO/JOJO/JAJO.
Source: ReflectionBenchmark.java.

text
Benchmark                                            Mode  Cnt   Score   Error  Units
ReflectionBenchmark.reflection_ctor_native           avgt   24   6.532 ± 0.512  ns/op baseline
ReflectionBenchmark.reflection_ctor_reflect          avgt   24  10.107 ± 0.059  ns/op
ReflectionBenchmark.reflection_ctor_methodHandle     avgt   24   9.156 ± 0.664  ns/op
ReflectionBenchmark.reflection_ctor_lambda           avgt   24   6.067 ± 0.064  ns/op (0.93x faster)

ReflectionBenchmark.reflection_getter_native         avgt   24   0.648 ± 0.018  ns/op baseline
ReflectionBenchmark.reflection_getter_reflect        avgt   24   4.184 ± 0.027  ns/op
ReflectionBenchmark.reflection_getter_methodHandle   avgt   24   3.104 ± 0.034  ns/op
ReflectionBenchmark.reflection_getter_lambda         avgt   24   0.796 ± 0.024  ns/op (1.23x slower)

ReflectionBenchmark.reflection_setter_native         avgt   24   0.764 ± 0.023  ns/op baseline
ReflectionBenchmark.reflection_setter_reflect        avgt   24   4.376 ± 0.041  ns/op
ReflectionBenchmark.reflection_setter_methodHandle   avgt   24   3.040 ± 0.006  ns/op
ReflectionBenchmark.reflection_setter_lambda         avgt   24   0.996 ± 0.007  ns/op (1.30x slower)

Summary:

  • SJF4J uses lambda-based accessors to minimize reflection overhead, enabling dynamic object manipulation with near-native performance.

JSON Binding Benchmark ​

This benchmark measures the additional structural overhead introduced by SJF4J on top of native JSON parsers.

SJF4J adds structural capabilities to the OBNT model, such as JOJO, @NodeValue, and @OneOf, while attempting to minimize additional overhead.

To bridge different JSON libraries, SJF4J provides three streaming integration modes:

  • SHARED_IO — reuse a shared IO pipeline across parsers
  • EXCLUSIVE_IO — delegate exclusive streaming control to the underlying library
  • PLUGIN_MODULE — integrate through a dedicated module implementation

Performance characteristics vary depending on the backend and workload, and no single mode is universally optimal.

Sample JSON (~1 KB) with nested objects and arrays.
Source: ReadBenchmark.java

text
Benchmark                           (streamingMode)  Mode  Cnt   Score   Error  Units
Read.json_jackson_native_has_any                N/A  avgt   20   3.114 ± 0.123  us/op baseline
Read.json_jackson_facade_jojo             SHARED_IO  avgt   20   3.145 ± 0.063  us/op
Read.json_jackson_facade_jojo          EXCLUSIVE_IO  avgt   20   2.845 ± 0.038  us/op (0.91x faster)
Read.json_jackson_facade_jojo         PLUGIN_MODULE  avgt   20   3.055 ± 0.050  us/op (0.98x faster)

Read.json_jackson_native_pojo                   N/A  avgt   20   1.661 ± 0.033  us/op baseline
Read.json_jackson_facade_pojo             SHARED_IO  avgt   20   2.263 ± 0.043  us/op
Read.json_jackson_facade_pojo          EXCLUSIVE_IO  avgt   20   2.104 ± 0.004  us/op
Read.json_jackson_facade_pojo         PLUGIN_MODULE  avgt   20   1.627 ± 0.021  us/op (0.98x faster)

-- no baseline
Read.json_gson_facade_jojo                SHARED_IO  avgt   20   3.692 ± 0.056  us/op
Read.json_gson_facade_jojo             EXCLUSIVE_IO  avgt   20   3.699 ± 0.065  us/op
Read.json_gson_facade_jojo            PLUGIN_MODULE  avgt   20   3.782 ± 0.031  us/op

Read.json_gson_native_pojo                      N/A  avgt   20   2.560 ± 0.038  us/op baseline
Read.json_gson_facade_pojo                SHARED_IO  avgt   20   2.644 ± 0.029  us/op
Read.json_gson_facade_pojo             EXCLUSIVE_IO  avgt   20   2.512 ± 0.018  us/op (0.98x faster)
Read.json_gson_facade_pojo            PLUGIN_MODULE  avgt   20   2.553 ± 0.027  us/op

Read.json_fastjson2_native_has_any              N/A  avgt   20   2.174 ± 0.039  us/op baseline
Read.json_fastjson2_facade_jojo           SHARED_IO  avgt   20   2.481 ± 0.043  us/op
Read.json_fastjson2_facade_jojo        EXCLUSIVE_IO  avgt   20   2.337 ± 0.048  us/op
Read.json_fastjson2_facade_jojo       PLUGIN_MODULE  avgt   20   2.232 ± 0.038  us/op (1.03x slower)

Read.json_fastjson2_native_pojo                 N/A  avgt   20   0.768 ± 0.004  us/op baseline
Read.json_fastjson2_facade_pojo           SHARED_IO  avgt   20   1.565 ± 0.119  us/op
Read.json_fastjson2_facade_pojo        EXCLUSIVE_IO  avgt   20   1.211 ± 0.032  us/op
Read.json_fastjson2_facade_pojo       PLUGIN_MODULE  avgt   20   0.780 ± 0.006  us/op (1.02x slower)

Read.json_jsonp_facade_jojo               SHARED_IO  avgt   20   4.694 ± 0.061  us/op
Read.json_jsonp_facade_pojo               SHARED_IO  avgt   20   3.275 ± 0.087  us/op

Read.json_simple_facade_jojo              SHARED_IO  avgt   20   8.372 ± 0.081  us/op
Read.json_simple_facade_pojo              SHARED_IO  avgt   20   7.635 ± 0.071  us/op

Summary

  • Jackson — Default PLUGIN_MODULE, SJF4J achieves near-parity performance with native Jackson.
    When using EXCLUSIVE_IO, SJF4J can be slightly faster with JOJO, but slower with POJO.

  • Gson — Default EXCLUSIVE_IO, SJF4J performs slightly faster than the native Gson.
    Gson’s native POJO binding does not support extra properties, while SJF4J does.

  • Fastjson2 — Default PLUGIN_MODULE, SJF4J achieves near-parity performance with native Fastjson2.
    Fastjson2 still has a noticeable advantage in POJO binding.

  • Overall performance in our benchmarks roughly follows: Fastjson2 > Jackson > Gson > JSON-P (Parsson) > Simple (built-in)

Note: Regardless of the underlying JSON parser, SJF4J ensures consistent behavior at the API level.

JSON Path Benchmark ​

This benchmark compares SJF4J with Jayway JsonPath using JMH.
To keep the comparison fair, the main results focus on compile and query over the same in-memory model, rather than parse + query with different parser stacks.

In the benchmark names, _jsonnode_ means the Jackson JsonNode model, while _maplist_ means the JDK Map + List model.

Source: JsonPathCompareBenchmark.java

text
Benchmark                                                    (expr)  Mode  Cnt     Score    Error  Units
compile_jayway                                $.store.book[1].price  avgt   16   170.368 ± 61.792  ns/op
compile_jayway                                $.store.bicycle.color  avgt   16   101.054 ± 60.623  ns/op
compile_jayway                               $.store.book[*].author  avgt   16    93.501 ±  0.951  ns/op
compile_jayway                                             $..price  avgt   16    43.169 ±  0.460  ns/op
compile_jayway                    $.store.book[?(@.price>10)].title  avgt   16   423.596 ±  2.417  ns/op
compile_jayway                              $.store.book[0,2].title  avgt   16   222.436 ± 22.619  ns/op
compile_sjf4j                                 $.store.book[1].price  avgt   16   101.364 ±  4.972  ns/op
compile_sjf4j                                 $.store.bicycle.color  avgt   16    60.924 ±  0.249  ns/op
compile_sjf4j                                $.store.book[*].author  avgt   16    70.906 ±  2.251  ns/op
compile_sjf4j                                              $..price  avgt   16    32.863 ±  0.249  ns/op
compile_sjf4j                     $.store.book[?(@.price>10)].title  avgt   16   377.336 ± 34.203  ns/op
compile_sjf4j                               $.store.book[0,2].title  avgt   16   117.516 ±  4.035  ns/op

query_jsonnode_definite_jayway                $.store.book[1].price  avgt   16   249.902 ±  8.303  ns/op
query_jsonnode_definite_jayway                $.store.bicycle.color  avgt   16   223.630 ±  0.487  ns/op
query_jsonnode_definite_sjf4j                 $.store.book[1].price  avgt   16   124.094 ±  1.636  ns/op
query_jsonnode_definite_sjf4j                 $.store.bicycle.color  avgt   16    85.514 ±  6.435  ns/op

query_jsonnode_indefinite_jayway             $.store.book[*].author  avgt   16   857.577 ± 78.340  ns/op
query_jsonnode_indefinite_jayway                           $..price  avgt   16  3785.889 ± 47.246  ns/op
query_jsonnode_indefinite_jayway  $.store.book[?(@.price>10)].title  avgt   16  1704.644 ± 23.227  ns/op
query_jsonnode_indefinite_jayway            $.store.book[0,2].title  avgt   16   464.221 ±  6.294  ns/op
query_jsonnode_indefinite_sjf4j              $.store.book[*].author  avgt   16   342.072 ±  1.608  ns/op
query_jsonnode_indefinite_sjf4j                            $..price  avgt   16  1911.318 ± 30.105  ns/op
query_jsonnode_indefinite_sjf4j   $.store.book[?(@.price>10)].title  avgt   16  1264.369 ± 28.331  ns/op
query_jsonnode_indefinite_sjf4j             $.store.book[0,2].title  avgt   16   232.189 ±  2.363  ns/op

query_maplist_definite_jayway                 $.store.book[1].price  avgt   16   247.470 ±  3.935  ns/op
query_maplist_definite_jayway                 $.store.bicycle.color  avgt   16   143.477 ±  4.889  ns/op
query_maplist_definite_sjf4j                  $.store.book[1].price  avgt   16    36.643 ±  0.087  ns/op
query_maplist_definite_sjf4j                  $.store.bicycle.color  avgt   16    26.284 ±  0.042  ns/op

query_maplist_indefinite_jayway              $.store.book[*].author  avgt   16  1055.750 ±  8.188  ns/op
query_maplist_indefinite_jayway                            $..price  avgt   16  2511.681 ± 18.358  ns/op
query_maplist_indefinite_jayway   $.store.book[?(@.price>10)].title  avgt   16  1866.102 ± 38.002  ns/op
query_maplist_indefinite_jayway             $.store.book[0,2].title  avgt   16   563.458 ± 18.850  ns/op
query_maplist_indefinite_sjf4j               $.store.book[*].author  avgt   16   147.899 ±  0.727  ns/op
query_maplist_indefinite_sjf4j                             $..price  avgt   16   524.305 ± 19.131  ns/op
query_maplist_indefinite_sjf4j    $.store.book[?(@.price>10)].title  avgt   16   830.208 ± 13.403  ns/op
query_maplist_indefinite_sjf4j              $.store.book[0,2].title  avgt   16   110.346 ±  5.904  ns/op

query_pojo_definite_sjf4j                     $.store.book[1].price  avgt   16   101.030 ±  2.058  ns/op
query_pojo_definite_sjf4j                     $.store.bicycle.color  avgt   16    83.222 ±  2.614  ns/op
query_pojo_indefinite_sjf4j                  $.store.book[*].author  avgt   16   338.385 ±  5.152  ns/op
query_pojo_indefinite_sjf4j                                $..price  avgt   16  1085.178 ± 13.573  ns/op
query_pojo_indefinite_sjf4j       $.store.book[?(@.price>10)].title  avgt   16  1066.040 ± 12.833  ns/op
query_pojo_indefinite_sjf4j                 $.store.book[0,2].title  avgt   16   227.114 ±  5.777  ns/op

query_jojo_definite_sjf4j                     $.store.book[1].price  avgt   16    48.522 ±  0.231  ns/op
query_jojo_definite_sjf4j                     $.store.bicycle.color  avgt   16    38.667 ±  0.294  ns/op
query_jojo_indefinite_sjf4j                  $.store.book[*].author  avgt   16   209.093 ±  0.957  ns/op
query_jojo_indefinite_sjf4j                                $..price  avgt   16   959.550 ± 14.941  ns/op
query_jojo_indefinite_sjf4j       $.store.book[?(@.price>10)].title  avgt   16   887.293 ± 16.033  ns/op
query_jojo_indefinite_sjf4j                 $.store.book[0,2].title  avgt   16   130.565 ±  1.011  ns/op

SJF4J vs Jayway

Geometric mean, lower is better:

Benchmark groupSJF4JJaywayResult
compile92.786 ns/op136.777 ns/opSJF4J 1.47x faster
query_jsonnode_definite103.013 ns/op236.401 ns/opSJF4J 2.29x faster
query_jsonnode_indefinite661.899 ns/op1266.047 ns/opSJF4J 1.91x faster
query_maplist_definite31.034 ns/op188.431 ns/opSJF4J 6.07x faster
query_maplist_indefinite290.317 ns/op1292.203 ns/opSJF4J 4.45x faster

In addition to query APIs, SJF4J also provides mutation APIs such as put, ensurePut and add/replace/remove.

SJF4J Object Model Comparison

SJF4J can run JSON Path directly over multiple Java object models.
For native Java object graphs, Map/List is still fastest. JOJO stays close to Map/List and remains clearly ahead of plain POJO, especially on definite queries.

Benchmark groupMap/ListJOJOPOJO
definite31.034 ns/op43.315 ns/op91.695 ns/op
indefinite290.317 ns/op390.459 ns/op546.050 ns/op

Summary:

  • SJF4J shows strong performance in compile and query workloads, and provides comprehensive mutation operations.
  • Within SJF4J, Map/List gives the best raw speed, while JOJO stays much closer to Map/List than plain POJO does.

@CompiledPath with APT ​

@CompiledPath brings JSONPath execution from runtime to compile time.

Instead of parsing and interpreting path expressions on every invocation, SJF4J generates dedicated Java accessors for @CompiledPath.

Source: CompiledPathBenchmark.java

text
Benchmark                                          Mode  Cnt    Score   Error  Units
get_bookPrice_jsonpath                             avgt    5   92.485 ± 3.447  ns/op
get_bookPrice_compiledpath                         avgt    5    1.793 ± 0.034  ns/op
get_bookPrice_native                               avgt    5    1.627 ± 0.012  ns/op

get_color_jsonpath                                 avgt    5   91.491 ± 0.658  ns/op
get_color_compiledpath                             avgt    5    0.988 ± 0.006  ns/op
get_color_native                                   avgt    5    0.877 ± 0.032  ns/op

get_price_jsonpath                                 avgt    5   80.996 ± 5.067  ns/op
get_price_compiledpath                             avgt    5    0.984 ± 0.004  ns/op
get_price_native                                   avgt    5    0.949 ± 0.081  ns/op

put_bookPrice_jsonpath                             avgt    5   99.874 ± 1.089  ns/op
put_bookPrice_compiledpath                         avgt    5   18.911 ± 0.884  ns/op
put_bookPrice_native                               avgt    5   18.697 ± 1.175  ns/op

put_price_jsonpath                                 avgt    5   86.607 ± 0.693  ns/op
put_price_compiledpath                             avgt    5   19.587 ± 1.648  ns/op
put_price_native                                   avgt    5   19.157 ± 0.609  ns/op

ensurePut_missing_price_jsonpath                   avgt    5  180.904 ± 0.606  ns/op
ensurePut_missing_price_compiledpath               avgt    5   17.557 ± 1.359  ns/op
ensurePut_missing_price_native                     avgt    5   17.603 ± 2.551  ns/op
OperationJsonPathCompiledPathResult
get_bookPrice92.485 ns/op1.793 ns/op51.58x faster
get_color91.491 ns/op0.988 ns/op92.60x faster
get_price80.996 ns/op0.984 ns/op82.31x faster
put_bookPrice99.874 ns/op18.911 ns/op5.28x faster
put_price86.607 ns/op19.587 ns/op4.42x faster
ensurePut_missing_price180.904 ns/op17.557 ns/op10.30x faster

Summary:

Although JsonPath is already one of the fastest JSONPath implementations available, @CompiledPath goes one step further (speedups range from 4× to over 90×).

Instead of optimizing JSONPath execution, @CompiledPath eliminates it.

JSON Schema Validation Benchmark ​

Creek Service ​

  • Creek Service's JVM JSON Schema validation comparison provides an additional third-party benchmark view.
  • In its performance comparison, SJF4J shows strong pure validation performance and is especially effective in serde-style workflows, where it can validate Java object graphs directly without an extra parse/build step.

Bowtie ​

According to the official JSON Schema Bowtie benchmark, performance can be evaluated locally using:

shell
bowtie perf -i java-sjf4j -i java-json-schema -i java-networknt-json-schema-validator -D draft2020-12

Sample result:

text
                                    Tests with Draft2020-12_MetaSchema                                     
                                                                                                           
 Test Name                java-sjf4j     java-json-schema            java-networknt-json-schema-validator  
────────────────────────────────────────────────────────────────────────────────────────────────────────── 
 Validating metaschema    35ms +- 2ms    74ms +- 5ms: 2.13x slower   74ms +- 3ms: 2.15x slower             
                          Reference      2.13x slower                2.15x slower                          
                                                                                                           
                                                                                                           
                                    Tests with OpenAPI_Spec_Schema                                         
                                                                                                           
 Test Name                  java-sjf4j     java-networknt-json-schema-validator   java-json-schema         
────────────────────────────────────────────────────────────────────────────────────────────────────────── 
 Non-OAuth Scopes Example   52ms +- 4ms    76ms +- 4ms: 1.46x slower              98ms +- 6ms: 1.87x slower
 Webhook Example            55ms +- 3ms    70ms +- 2ms: 1.28x slower              93ms +- 4ms: 1.7x slower 
                            Reference      1.37x slower                           1.78x slower             
                                                                                                           
                                    Tests with useless_keywords                                            
                                                                                                           
 Test Name             java-sjf4j       java-networknt-json-schema-validator   java-json-schema            
────────────────────────────────────────────────────────────────────────────────────────────────────────── 
 Beginning of schema   399ms +- 10ms    521ms +- 21ms: 1.31x slower            569ms +- 11ms: 1.43x slower 
 Middle of schema      390ms +- 5ms     520ms +- 12ms: 1.33x slower            564ms +- 6ms: 1.45x slower  
 End of schema         411ms +- 14ms    538ms +- 16ms: 1.31x slower            586ms +- 14ms: 1.42x slower 
 Valid                 396ms +- 10ms    525ms +- 19ms: 1.33x slower            585ms +- 15ms: 1.48x slower 
                       Reference        1.32x slower                           1.44x slower                
                                                                                                           
                                    Tests with nested_schemas                                              
                                                                                                           
 Test Name         java-sjf4j       java-json-schema            java-networknt-json-schema-validator       
────────────────────────────────────────────────────────────────────────────────────────────────────────── 
 No of Levels 1    31ms +- 850us    69ms +- 4ms: 2.25x slower   70ms +- 2ms: 2.26x slower                  
 No of Levels 4    29ms +- 2ms      72ms +- 3ms: 2.46x slower   73ms +- 3ms: 2.5x slower                   
 No of Levels 7    31ms +- 535us    71ms +- 3ms: 2.27x slower   74ms +- 2ms: 2.36x slower                  
 No of Levels 10   32ms +- 1ms      75ms +- 4ms: 2.37x slower   75ms +- 3ms: 2.36x slower                  
                   Reference        2.34x slower                2.37x slower

Summary:

  • Creek Service: SJF4J stands out both for fast pure validation and for efficient serde-style validation over Java object graphs.
  • Bowtie: SJF4J ranks among the top-tier of Java implementations.

Object-to-object Mapping Benchmark ​

This benchmark compares SJF4J generated mappers with MapStruct and direct hand-written mapping for the currently supported basic mapper subset.

Source: CompiledMapperBenchmark.java

text
Benchmark                                     Mode  Cnt    Score     Error  Units
CompiledMapperBenchmark.flat_hand             avgt    5   10.724 ±   1.698  ns/op
CompiledMapperBenchmark.flat_mapstruct        avgt    5   10.754 ±   0.555  ns/op
CompiledMapperBenchmark.flat_sjf4j            avgt    5   11.296 ±   0.794  ns/op

CompiledMapperBenchmark.list_flat_hand        avgt    5  486.478 ±  15.869  ns/op
CompiledMapperBenchmark.list_flat_mapstruct   avgt    5  502.587 ± 140.311  ns/op
CompiledMapperBenchmark.list_flat_sjf4j       avgt    5  479.231 ±   8.346  ns/op

CompiledMapperBenchmark.multi_hand            avgt    5    2.970 ±   0.069  ns/op
CompiledMapperBenchmark.multi_mapstruct       avgt    5    3.146 ±   0.042  ns/op
CompiledMapperBenchmark.multi_sjf4j           avgt    5    3.145 ±   0.054  ns/op

CompiledMapperBenchmark.update_hand           avgt    5   12.366 ±   0.550  ns/op
CompiledMapperBenchmark.update_mapstruct      avgt    5   11.046 ±   0.224  ns/op
CompiledMapperBenchmark.update_sjf4j          avgt    5   11.275 ±   0.436  ns/op

Summary:

  • @CompiledMapper performs at about the same speed as MapStruct and hand-written mapping in these benchmarks.
  • Java Object Mapper Benchmark: SJF4J performs competitively with the fastest Java object mappers.

JDBC ResultSet Mapping Benchmark ​

This benchmark maps a 1,000-row H2 ResultSet to User objects or maps.
SQL execution runs during JMH setup, so the timed work is limited to result-set traversal and conversion. It does not measure database, network, or connection-pool costs.

Source: CompiledJdbcMapperBenchmark.java

text
Benchmark                                       Mode  Cnt  Score   Error  Units
users_handwritten_by_index                      avgt   10  0.034 ± 0.009  ms/op
users_handwritten_by_label                      avgt   10  0.047 ± 0.003  ms/op
users_mybatis_DefaultResultSetHandler_auto      avgt   10  0.299 ± 0.006  ms/op
users_mybatis_DefaultResultSetHandler_explicit  avgt   10  0.411 ± 0.008  ms/op
users_spring_BeanPropertyRowMapper              avgt   10  0.406 ± 0.003  ms/op
users_sjf4j                                     avgt   10  0.026 ± 0.001  ms/op

maps_handwritten                                avgt   10  0.074 ± 0.003  ms/op
maps_sjf4j                                      avgt   10  0.072 ± 0.016  ms/op

Summary:

  • The generated SJF4J mapper is close to hand-written mapping for both maps and JavaBeans.
  • For User mapping, SJF4J is about 15x faster than the measured MyBatis paths and Spring's BeanPropertyRowMapper.