Scalability of JVM processes is limited by GC rate.
For contemporary CPUs and GCs that provide the best throughput the allocation limit is ~11Gb/sec.
After reaching the allocation limit the JVM process doesn't scale.
Having 7.5Gb/sec in 1 thread the limit will be reached at 2-4 threads and adding more threads only decrease the total troughput.
Steps to reproduce that by running JSON parsing benchmarks on your JDK:
- Install latest version of
sbt
and/or ensure that it already installed properly:
sbt about
- Clone
jsoniter-scala
repo:
git clone --depth 1 https://github.com/plokhotnyuk/jsoniter-scala.git
- Enter to the cloned directory:
cd jsoniter-scala
- Run benchmarks replacing
<n>
by 1, 2, 4, 8, and 16 (the number of parsing threads):
sbt 'jsoniter-scala-benchmarkJVM/jmh:run -t <n> -prof gc -p size=128 ArrayOfCharsReading.(zioJson|jsoniterScala)'
Below are results of benchmarks that parse JSON array of 1-char JSON strings to Array[Char]
using using zio-json and jsoniter-scala.
The parallel GC is used with ParallelGCThreads = 13 (default on the tested environmant), to set explicitly use -XX:ParallelGCThreads=<n>
, where <n>
should be replaced by a number of GC threads.
Environment: Intel® Core™ i9-11900H CPU @ 2.5GHz (max 4.9GHz), RAM 32Gb DDR4-3200, Ubuntu 22.04, and latest versions of Azul Zulu 1
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayOfCharsReading.jsoniterScala 128 thrpt 5 1803944.618 ± 41321.739 ops/s
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate 128 thrpt 5 623.582 ± 14.049 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate.norm 128 thrpt 5 544.018 ± 0.025 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space 128 thrpt 5 613.826 ± 879.374 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 535.326 ± 763.468 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.013 ± 0.050 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 0.012 ± 0.044 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.count 128 thrpt 5 6.000 counts
[info] ArrayOfCharsReading.jsoniterScala:·gc.time 128 thrpt 5 8.000 ms
[info] ArrayOfCharsReading.zioJson 128 thrpt 5 367381.109 ± 9385.923 ops/s
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate 128 thrpt 5 7453.477 ± 191.421 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate.norm 128 thrpt 5 31920.995 ± 0.160 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space 128 thrpt 5 7471.190 ± 1080.227 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 31995.178 ± 4337.185 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.329 ± 0.208 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 1.409 ± 0.896 B/op
[info] ArrayOfCharsReading.zioJson:·gc.count 128 thrpt 5 73.000 counts
[info] ArrayOfCharsReading.zioJson:·gc.time 128 thrpt 5 40.000 ms
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayOfCharsReading.jsoniterScala 128 thrpt 5 3262574.427 ± 64212.694 ops/s
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate 128 thrpt 5 1127.925 ± 22.327 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate.norm 128 thrpt 5 544.021 ± 0.018 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space 128 thrpt 5 1125.598 ± 880.921 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 542.912 ± 425.070 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.846 ± 7.024 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 0.410 ± 3.408 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.count 128 thrpt 5 11.000 counts
[info] ArrayOfCharsReading.jsoniterScala:·gc.time 128 thrpt 5 10.000 ms
[info] ArrayOfCharsReading.zioJson 128 thrpt 5 514184.868 ± 4543.376 ops/s
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate 128 thrpt 5 10422.398 ± 91.917 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate.norm 128 thrpt 5 31896.977 ± 0.064 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space 128 thrpt 5 10437.287 ± 1080.341 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 31943.709 ± 3499.154 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.400 ± 0.291 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 1.223 ± 0.885 B/op
[info] ArrayOfCharsReading.zioJson:·gc.count 128 thrpt 5 102.000 counts
[info] ArrayOfCharsReading.zioJson:·gc.time 128 thrpt 5 46.000 ms
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayOfCharsReading.jsoniterScala 128 thrpt 5 6293147.286 ± 1191058.026 ops/s
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate 128 thrpt 5 2175.291 ± 412.018 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate.norm 128 thrpt 5 544.019 ± 0.008 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space 128 thrpt 5 2250.919 ± 1079.229 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 563.004 ± 248.343 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.042 ± 0.057 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 0.010 ± 0.013 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.count 128 thrpt 5 22.000 counts
[info] ArrayOfCharsReading.jsoniterScala:·gc.time 128 thrpt 5 9.000 ms
[info] ArrayOfCharsReading.zioJson 128 thrpt 5 535169.029 ± 6592.923 ops/s
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate 128 thrpt 5 10846.887 ± 132.774 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate.norm 128 thrpt 5 31896.972 ± 0.104 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space 128 thrpt 5 10947.448 ± 1083.443 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 32194.627 ± 3511.139 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.495 ± 0.280 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 1.457 ± 0.840 B/op
[info] ArrayOfCharsReading.zioJson:·gc.count 128 thrpt 5 107.000 counts
[info] ArrayOfCharsReading.zioJson:·gc.time 128 thrpt 5 40.000 ms
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayOfCharsReading.jsoniterScala 128 thrpt 5 10900561.711 ± 661598.038 ops/s
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate 128 thrpt 5 3766.625 ± 229.334 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate.norm 128 thrpt 5 544.018 ± 0.005 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space 128 thrpt 5 3784.244 ± 1080.053 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 546.501 ± 148.032 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.075 ± 0.166 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 0.011 ± 0.023 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.count 128 thrpt 5 37.000 counts
[info] ArrayOfCharsReading.jsoniterScala:·gc.time 128 thrpt 5 12.000 ms
[info] ArrayOfCharsReading.zioJson 128 thrpt 5 496724.659 ± 13676.717 ops/s
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate 128 thrpt 5 10066.491 ± 280.478 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate.norm 128 thrpt 5 31896.985 ± 0.057 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space 128 thrpt 5 10123.091 ± 880.887 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 32074.971 ± 2336.857 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.379 ± 0.280 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 1.199 ± 0.873 B/op
[info] ArrayOfCharsReading.zioJson:·gc.count 128 thrpt 5 99.000 counts
[info] ArrayOfCharsReading.zioJson:·gc.time 128 thrpt 5 32.000 ms
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayOfCharsReading.jsoniterScala 128 thrpt 5 11230335.635 ± 44550.991 ops/s
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate 128 thrpt 5 3881.520 ± 18.729 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.alloc.rate.norm 128 thrpt 5 544.019 ± 0.005 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space 128 thrpt 5 3873.084 ± 1101.210 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 542.841 ± 154.625 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.100 ± 0.222 MB/sec
[info] ArrayOfCharsReading.jsoniterScala:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 0.014 ± 0.031 B/op
[info] ArrayOfCharsReading.jsoniterScala:·gc.count 128 thrpt 5 38.000 counts
[info] ArrayOfCharsReading.jsoniterScala:·gc.time 128 thrpt 5 9.000 ms
[info] ArrayOfCharsReading.zioJson 128 thrpt 5 464041.176 ± 1826.740 ops/s
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate 128 thrpt 5 9421.986 ± 72.543 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.alloc.rate.norm 128 thrpt 5 31897.095 ± 0.531 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space 128 thrpt 5 9568.482 ± 821.021 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Eden_Space.norm 128 thrpt 5 32392.991 ± 2760.087 B/op
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space 128 thrpt 5 0.124 ± 0.224 MB/sec
[info] ArrayOfCharsReading.zioJson:·gc.churn.PS_Survivor_Space.norm 128 thrpt 5 0.420 ± 0.758 B/op
[info] ArrayOfCharsReading.zioJson:·gc.count 128 thrpt 5 94.000 counts
[info] ArrayOfCharsReading.zioJson:·gc.time 128 thrpt 5 22.000 ms