Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON serialization refactoring and optimization #1506

Merged
merged 1 commit into from Mar 21, 2023

Conversation

tomatosalat0
Copy link
Contributor

Summary

  • JSON.stringify now completes in about 60-50% of the time to complete the serialization. These numbers do apply when serializing plain objects without complex replacer or with custom toJSON methods. If you specify a spacer to beautify your generated JSONs, the serializer will take a little bit more time (see the table below), but still be faster compared to the previous revision.
  • JSON.stringify now only allocates about 20% of the previously required memory during that process

Optimization

So long story short, the JSON serializer now uses a two StringBuilder for the complete operation instead of getting new ones quite often during the execution. One is used to build the JSON string itself and a second small one gets used when numbers get serialized.

The behavior of the serializer hasn't changed. The generated output will be the same as before.

Benchmarks

Setup

Like the in JSON.parse optimization process, I used several JSON files to measure the performance differences. Before executing the Benchmark, these JSON files are deserialized using the Jint JsonParser and then serialized back inside the benchmark method body. The benchmarks body basically looks like like this:

[Benchmark]
public void NewSerializerFormatted()
{
    JsonSerializer serializer = new JsonSerializer(_engine);
    serializer.Serialize(_toSerialize); // _toSerialize is the JsValue returned from JSON.parse
}

This time, I benched two calls: one without any spacer defined and one with spacer-value (serializer.Serialize(_toSerialize, JsValue.Undefined, new JsString(" "));)

These are the JSON-files used for the benchmarks

The JSON files for the test have a size between 2.7KB and 43.3MB (UTF-8 encoded).

Results

As like before, the table is huge. The relevant columns are "Ratio" and "Alloc Ratio".

  • OldSerializerFormatted is the previous serializer, executed with two spaces for the space parameter
  • OldSerializerUnformatted is the previous serializer, executed without any spacer
  • NewSerializerXYZ is the same, but the new code
BenchmarkDotNet=v0.13.4, OS=Windows 10 (10.0.19042.2251/20H2/October2020Update)
AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores
.NET SDK=7.0.202
  [Host]     : .NET 6.0.15 (6.0.1523.11507), X64 RyuJIT AVX2
  DefaultJob : .NET 6.0.15 (6.0.1523.11507), X64 RyuJIT AVX2

Method FileName Mean Error StdDev Ratio RatioSD Gen0 Gen1 Gen2 Allocated Alloc Ratio
OldSerializerFormatted algol(...)ation [31] 683,145.49 μs 7,773.648 μs 6,891.137 μs 1.00 0.00 49000.0000 13000.0000 - 988451.47 KB 1.00
NewSerializerFormatted algol(...)ation [31] 388,183.85 μs 5,788.998 μs 5,415.033 μs 0.57 0.01 12000.0000 5000.0000 - 296073.65 KB 0.30
OldSerializerFormatted australia-abc 348.42 μs 2.368 μs 2.215 μs 1.00 0.00 66.4063 15.6250 - 1090.33 KB 1.00
NewSerializerFormatted australia-abc 198.81 μs 1.257 μs 1.176 μs 0.57 0.01 15.1367 3.6621 - 250.41 KB 0.23
OldSerializerFormatted bestbuy_dataset 251,559.43 μs 3,728.770 μs 3,487.894 μs 1.00 0.00 20000.0000 6000.0000 500.0000 411267.09 KB 1.00
NewSerializerFormatted bestbuy_dataset 167,054.41 μs 3,141.535 μs 3,361.407 μs 0.66 0.02 5333.3333 3333.3333 666.6667 121625.39 KB 0.30
OldSerializerFormatted bitcoin 210.83 μs 1.919 μs 1.701 μs 1.00 0.00 45.1660 8.7891 - 739.25 KB 1.00
NewSerializerFormatted bitcoin 115.01 μs 0.580 μs 0.542 μs 0.55 0.00 9.2773 1.5869 - 153.51 KB 0.21
OldSerializerFormatted canada 97,960.85 μs 1,904.290 μs 3,233.629 μs 1.00 0.00 6833.3333 4833.3333 3000.0000 202056.34 KB 1.00
NewSerializerFormatted canada 43,466.37 μs 749.058 μs 700.669 μs 0.44 0.02 1769.2308 1153.8462 615.3846 31033.46 KB 0.15
OldSerializerFormatted citm_catalog 30,492.14 μs 106.101 μs 99.247 μs 1.00 0.00 3437.5000 2437.5000 1000.0000 51432.26 KB 1.00
NewSerializerFormatted citm_catalog 11,833.41 μs 196.593 μs 183.893 μs 0.39 0.01 718.7500 484.3750 250.0000 10152.14 KB 0.20
OldSerializerFormatted doj-blog 888.85 μs 11.427 μs 10.689 μs 1.00 0.00 454.1016 454.1016 454.1016 3175.7 KB 1.00
NewSerializerFormatted doj-blog 486.27 μs 2.199 μs 1.950 μs 0.55 0.01 90.8203 90.8203 90.8203 634.08 KB 0.20
OldSerializerFormatted eu-lobby-country 123.01 μs 1.251 μs 1.109 μs 1.00 0.00 23.1934 3.6621 - 381.02 KB 1.00
NewSerializerFormatted eu-lobby-country 77.38 μs 0.522 μs 0.488 μs 0.63 0.01 5.8594 0.9766 - 97.77 KB 0.26
OldSerializerFormatted eu-lobby-financial 783.66 μs 15.475 μs 15.198 μs 1.00 0.00 237.3047 237.3047 237.3047 1920.99 KB 1.00
NewSerializerFormatted eu-lobby-financial 418.62 μs 3.060 μs 2.556 μs 0.54 0.01 47.3633 47.3633 47.3633 437.55 KB 0.23
OldSerializerFormatted eu-lobby-repr 1,670.34 μs 22.008 μs 20.586 μs 1.00 0.00 554.6875 554.6875 554.6875 4215.33 KB 1.00
NewSerializerFormatted eu-lobby-repr 826.59 μs 4.240 μs 3.759 μs 0.50 0.01 110.3516 110.3516 110.3516 918.64 KB 0.22
OldSerializerFormatted github-events 1,284.82 μs 10.366 μs 9.697 μs 1.00 0.00 285.1563 142.5781 142.5781 4086.16 KB 1.00
NewSerializerFormatted github-events 633.99 μs 3.525 μs 3.298 μs 0.49 0.00 71.2891 71.2891 71.2891 711.58 KB 0.17
OldSerializerFormatted github-gists 725.52 μs 12.757 μs 11.309 μs 1.00 0.00 90.8203 90.8203 90.8203 1566.66 KB 1.00
NewSerializerFormatted github-gists 348.45 μs 1.649 μs 1.462 μs 0.48 0.01 45.4102 45.4102 45.4102 412.41 KB 0.26
OldSerializerFormatted inspe(...)yload [22] 470,566.69 μs 6,654.341 μs 5,898.900 μs 1.00 0.00 34000.0000 19000.0000 7000.0000 995097.57 KB 1.00
NewSerializerFormatted inspe(...)yload [22] 114,521.19 μs 1,658.612 μs 1,470.316 μs 0.24 0.00 5200.0000 3000.0000 600.0000 110157.08 KB 0.11
OldSerializerFormatted json-generator 116.39 μs 1.535 μs 1.436 μs 1.00 0.00 17.8223 1.5869 - 291.41 KB 1.00
NewSerializerFormatted json-generator 72.50 μs 0.469 μs 0.439 μs 0.62 0.01 5.4932 0.8545 - 90.92 KB 0.31
OldSerializerFormatted meteorites 10,006.58 μs 69.899 μs 61.964 μs 1.00 0.00 828.1250 546.8750 328.1250 9906.95 KB 1.00
NewSerializerFormatted meteorites 3,317.38 μs 24.334 μs 21.572 μs 0.33 0.00 199.2188 199.2188 199.2188 2914.12 KB 0.29
OldSerializerFormatted movies 93,649.51 μs 1,015.225 μs 949.642 μs 1.00 0.00 7500.0000 2833.3333 500.0000 136137.35 KB 1.00
NewSerializerFormatted movies 52,278.88 μs 582.231 μs 544.619 μs 0.56 0.01 2000.0000 1000.0000 300.0000 38746.8 KB 0.28
OldSerializerFormatted reddit-scala 1,511.92 μs 10.692 μs 9.478 μs 1.00 0.00 615.2344 615.2344 615.2344 4708.99 KB 1.00
NewSerializerFormatted reddit-scala 644.47 μs 3.396 μs 3.011 μs 0.43 0.00 83.0078 83.0078 83.0078 727.96 KB 0.15
OldSerializerFormatted rick-morty 238.72 μs 2.470 μs 2.190 μs 1.00 0.00 52.2461 10.4980 - 856.74 KB 1.00
NewSerializerFormatted rick-morty 134.37 μs 0.377 μs 0.315 μs 0.56 0.01 11.9629 2.9297 - 196.64 KB 0.23
OldSerializerFormatted temp-anomaly 92.85 μs 0.299 μs 0.265 μs 1.00 0.00 5.7373 0.2441 - 94.11 KB 1.00
NewSerializerFormatted temp-anomaly 74.46 μs 0.403 μs 0.358 μs 0.80 0.00 1.7090 - - 29.68 KB 0.32
OldSerializerFormatted thai-cinemas 140.35 μs 1.399 μs 1.241 μs 1.00 0.00 25.3906 3.6621 - 418.29 KB 1.00
NewSerializerFormatted thai-cinemas 76.83 μs 0.711 μs 0.665 μs 0.55 0.00 6.3477 0.8545 - 104.88 KB 0.25
OldSerializerFormatted turkish 15,232.91 μs 297.883 μs 407.746 μs 1.00 0.00 1687.5000 1406.2500 984.3750 22091.77 KB 1.00
NewSerializerFormatted turkish 6,821.00 μs 135.210 μs 296.789 μs 0.45 0.02 460.9375 367.1875 257.8125 4895.4 KB 0.22
OldSerializerFormatted twitter 13,508.75 μs 252.575 μs 280.736 μs 1.00 0.00 1750.0000 1359.3750 968.7500 18560.21 KB 1.00
NewSerializerFormatted twitter 3,776.76 μs 21.860 μs 19.379 μs 0.28 0.01 332.0313 332.0313 332.0313 3518.46 KB 0.19
OldSerializerFormatted twitt(...)ponse [28] 119.14 μs 0.681 μs 0.637 μs 1.00 0.00 24.7803 3.2959 - 405.59 KB 1.00
NewSerializerFormatted twitt(...)ponse [28] 69.48 μs 0.385 μs 0.341 μs 0.58 0.00 5.4932 0.8545 - 90.25 KB 0.22
OldSerializerFormatted twitter_api_response 131.16 μs 0.817 μs 0.764 μs 1.00 0.00 27.0996 3.4180 - 444.95 KB 1.00
NewSerializerFormatted twitter_api_response 76.96 μs 0.392 μs 0.367 μs 0.59 0.00 5.8594 0.8545 - 96.75 KB 0.22
OldSerializerUnformatted algol(...)ation [31] 615,988.31 μs 8,281.685 μs 7,746.693 μs 1.00 0.00 39000.0000 10000.0000 - 787109.97 KB 1.00
NewSerializerUnformatted algol(...)ation [31] 347,226.38 μs 3,207.867 μs 2,843.690 μs 0.56 0.01 10000.0000 4000.0000 - 242397.41 KB 0.31
OldSerializerUnformatted australia-abc 314.00 μs 5.294 μs 4.952 μs 1.00 0.00 51.7578 10.2539 - 852 KB 1.00
NewSerializerUnformatted australia-abc 183.62 μs 0.828 μs 0.734 μs 0.58 0.01 12.4512 2.9297 - 207.69 KB 0.24
OldSerializerUnformatted bestbuy_dataset 236,860.49 μs 1,434.191 μs 1,119.722 μs 1.00 0.00 17666.6667 5333.3333 666.6667 354690.78 KB 1.00
NewSerializerUnformatted bestbuy_dataset 137,904.51 μs 2,393.849 μs 2,239.208 μs 0.58 0.01 4750.0000 3250.0000 500.0000 107142.72 KB 0.30
OldSerializerUnformatted bitcoin 195.37 μs 1.004 μs 0.939 μs 1.00 0.00 31.7383 4.6387 - 522.2 KB 1.00
NewSerializerUnformatted bitcoin 109.46 μs 0.417 μs 0.348 μs 0.56 0.00 7.0801 0.9766 - 117.07 KB 0.22
OldSerializerUnformatted canada 64,085.19 μs 1,082.357 μs 1,012.437 μs 1.00 0.00 3888.8889 2444.4444 1111.1111 100418.99 KB 1.00
NewSerializerUnformatted canada 33,602.95 μs 658.807 μs 616.248 μs 0.52 0.01 937.5000 625.0000 250.0000 15737.25 KB 0.16
OldSerializerUnformatted citm_catalog 22,492.49 μs 193.875 μs 161.894 μs 1.00 0.00 1937.5000 1031.2500 500.0000 28700.84 KB 1.00
NewSerializerUnformatted citm_catalog 9,930.45 μs 175.368 μs 208.763 μs 0.44 0.01 484.3750 296.8750 125.0000 6955.75 KB 0.24
OldSerializerUnformatted doj-blog 855.85 μs 4.920 μs 4.362 μs 1.00 0.00 454.1016 454.1016 454.1016 3098.47 KB 1.00
NewSerializerUnformatted doj-blog 508.43 μs 5.068 μs 4.741 μs 0.59 0.01 90.8203 90.8203 90.8203 624.88 KB 0.20
OldSerializerUnformatted eu-lobby-country 113.18 μs 0.981 μs 0.917 μs 1.00 0.00 19.5313 0.3662 - 320.68 KB 1.00
NewSerializerUnformatted eu-lobby-country 66.37 μs 0.347 μs 0.324 μs 0.59 0.01 5.4932 0.7324 - 90.02 KB 0.28
OldSerializerUnformatted eu-lobby-financial 695.48 μs 3.586 μs 3.179 μs 1.00 0.00 191.4063 191.4063 191.4063 1560.36 KB 1.00
NewSerializerUnformatted eu-lobby-financial 391.93 μs 2.788 μs 2.608 μs 0.56 0.00 38.0859 38.0859 38.0859 372.06 KB 0.24
OldSerializerUnformatted eu-lobby-repr 1,797.03 μs 33.367 μs 31.211 μs 1.00 0.00 498.0469 498.0469 498.0469 3766.65 KB 1.00
NewSerializerUnformatted eu-lobby-repr 764.96 μs 4.191 μs 3.715 μs 0.43 0.01 99.6094 99.6094 99.6094 828.93 KB 0.22
OldSerializerUnformatted github-events 1,070.18 μs 12.422 μs 11.620 μs 1.00 0.00 234.3750 117.1875 117.1875 3310.45 KB 1.00
NewSerializerUnformatted github-events 565.97 μs 3.230 μs 2.864 μs 0.53 0.01 58.5938 58.5938 58.5938 586.54 KB 0.18
OldSerializerUnformatted github-gists 634.22 μs 8.169 μs 7.641 μs 1.00 0.00 76.1719 76.1719 76.1719 1356.6 KB 1.00
NewSerializerUnformatted github-gists 338.49 μs 1.660 μs 1.386 μs 0.53 0.01 38.0859 38.0859 38.0859 372.06 KB 0.27
OldSerializerUnformatted inspe(...)yload [22] 277,221.96 μs 4,967.367 μs 11,708.669 μs 1.00 0.00 20000.0000 7000.0000 4000.0000 494897.48 KB 1.00
NewSerializerUnformatted inspe(...)yload [22] 98,005.45 μs 1,188.018 μs 1,111.272 μs 0.34 0.02 3400.0000 1200.0000 200.0000 67977.36 KB 0.14
OldSerializerUnformatted json-generator 113.40 μs 0.623 μs 0.583 μs 1.00 0.00 13.9160 1.0986 - 227.76 KB 1.00
NewSerializerUnformatted json-generator 64.75 μs 0.302 μs 0.252 μs 0.57 0.00 4.8828 0.7324 - 81.45 KB 0.36
OldSerializerUnformatted meteorites 5,128.21 μs 60.415 μs 56.512 μs 1.00 0.00 562.5000 406.2500 281.2500 7681.91 KB 1.00
NewSerializerUnformatted meteorites 3,222.42 μs 21.024 μs 19.666 μs 0.63 0.01 140.6250 140.6250 140.6250 2365.84 KB 0.31
OldSerializerUnformatted movies 88,612.62 μs 1,467.693 μs 1,301.072 μs 1.00 0.00 5500.0000 2500.0000 333.3333 99319.64 KB 1.00
NewSerializerUnformatted movies 43,730.69 μs 488.550 μs 433.087 μs 0.49 0.01 1416.6667 666.6667 166.6667 28020.65 KB 0.28
OldSerializerUnformatted reddit-scala 1,235.14 μs 18.078 μs 16.910 μs 1.00 0.00 468.7500 468.7500 468.7500 3646.09 KB 1.00
NewSerializerUnformatted reddit-scala 629.95 μs 2.451 μs 2.293 μs 0.51 0.01 58.5938 58.5938 58.5938 593.59 KB 0.16
OldSerializerUnformatted rick-morty 228.02 μs 1.661 μs 1.387 μs 1.00 0.00 41.5039 9.2773 - 679.91 KB 1.00
NewSerializerUnformatted rick-morty 129.86 μs 0.560 μs 0.524 μs 0.57 0.00 9.7656 1.7090 - 161.45 KB 0.24
OldSerializerUnformatted temp-anomaly 88.56 μs 0.332 μs 0.310 μs 1.00 0.00 4.7607 0.2441 - 79.75 KB 1.00
NewSerializerUnformatted temp-anomaly 76.85 μs 0.333 μs 0.312 μs 0.87 0.00 1.3428 - - 23.84 KB 0.30
OldSerializerUnformatted thai-cinemas 126.86 μs 1.081 μs 1.011 μs 1.00 0.00 20.5078 2.6855 - 335.84 KB 1.00
NewSerializerUnformatted thai-cinemas 70.74 μs 0.698 μs 0.619 μs 0.56 0.01 5.7373 0.8545 - 95.67 KB 0.28
OldSerializerUnformatted turkish 15,284.55 μs 156.015 μs 138.303 μs 1.00 0.00 1593.7500 1375.0000 1000.0000 17471.31 KB 1.00
NewSerializerUnformatted turkish 5,587.92 μs 110.290 μs 222.791 μs 0.36 0.02 375.0000 289.0625 203.1250 3968.95 KB 0.23
OldSerializerUnformatted twitter 6,980.58 μs 77.399 μs 64.631 μs 1.00 0.00 1242.1875 1242.1875 1242.1875 13716.14 KB 1.00
NewSerializerUnformatted twitter 3,270.05 μs 17.604 μs 16.467 μs 0.47 0.01 246.0938 246.0938 246.0938 2810.07 KB 0.20
OldSerializerUnformatted twitt(...)ponse [28] 106.11 μs 0.972 μs 0.909 μs 1.00 0.00 18.1885 1.8311 - 299.16 KB 1.00
NewSerializerUnformatted twitt(...)ponse [28] 65.65 μs 0.319 μs 0.283 μs 0.62 0.01 4.8828 0.7324 - 80.57 KB 0.27
OldSerializerUnformatted twitter_api_response 121.02 μs 0.783 μs 0.732 μs 1.00 0.00 20.0195 2.1973 - 327.59 KB 1.00
NewSerializerUnformatted twitter_api_response 71.13 μs 0.337 μs 0.299 μs 0.59 0.00 5.2490 0.3662 - 86.12 KB 0.26

Copy link
Collaborator

@lahma lahma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work and performance improvement! 🚀

@lahma lahma merged commit 675815c into sebastienros:main Mar 21, 2023
2 checks passed
@tomatosalat0 tomatosalat0 deleted the json-stringify-performance branch March 21, 2023 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants