fsprojects / FSharp.Json

F# JSON Reflection based serialization library
Apache License 2.0
222 stars 26 forks source link

Performance optimisations: Using more value-types and structs #68

Open Thorium opened 8 months ago

Thorium commented 8 months ago

This commit reduces the memory usage and speeds up all the serialization.

I used also the benchmark-branch all the test that did have result for FSharp.Json, to run test between the current version and this commit, both run with latest FSharp.Core. Here are the results:

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.22621
13th Gen Intel Core i9-13900H, 1 CPU, 20 logical and 14 physical cores
.NET Core SDK=8.0.100-rc.1.23463.5
  [Host]     : .NET Core 2.0.9 (CoreCLR 4.6.26614.01, CoreFX 4.6.26614.01), 64bit RyuJIT DEBUG
  DefaultJob : .NET Core 2.0.9 (CoreCLR 4.6.26614.01, CoreFX 4.6.26614.01), 64bit RyuJIT
  1. BoxedArrayRoundtrip
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated Version
Newtonsoft.Json 3.680 us 0.0302 us 0.0282 us 2.2736 0.0076 - 14 KB 13.0.3
FSharp.Json 12.753 us 0.1331 us 0.1180 us 1.9531 0.0153 - 12.12 KB 0.4.1
FSharp.Json 12.187 us 0.1455 us 0.1361 us 1.8311 0.0153 - 11.41 KB This PR
  1. FSharpBinaryRoundtrip
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated Version
Newtonsoft.Json 21.00 ms 0.3417 ms 0.3196 ms 3156.25 968.75 375.0000 18.47 MB 13.0.3
FSharp.Json 120.64 ms 2.3876 ms 2.7495 ms 6600.00 200.00 - 40.88 MB 0.4.1
FSharp.Json 107.32 ms 1.5377 ms 1.4384 ms 6000.00 200.00 - 37.29 MB This PR
  1. FSharpListRoundtrip
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated Version
Newtonsoft.Json 111.8 us 1.560 us 1.459 us 15.7471 0.7324 - 97.62 KB 13.0.3
FSharp.Json 1,012.4 us 12.436 us 11.632 us 138.6719 21.4844 - 869.35 KB 0.4.1
FSharp.Json 997.4 us 11.905 us 10.553 us 126.9531 19.5313 - 798.89 KB This PR
  1. LargeTupleRoundtrip
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated Version
Newtonsoft.Json 7.808 us 0.0958 us 0.0896 us 2.6703 0.0305 - 16.59 KB 13.0.3
FSharp.Json 27.109 us 0.3354 us 0.3137 us 3.3569 0.0305 - 20.82 KB 0.4.1
FSharp.Json 26.810 us 0.5355 us 0.9656 us 3.1433 0.0305 - 19.59 KB This PR
Thorium commented 7 months ago

The figures are still so bad that people should prefer System.Text.Json and Newtonsoft.Json over this library.

bartelink commented 7 months ago

Yes, far too many moving parts If going NSJ (which is a bad idea for new systems as it's a dead end), FsCodec.NewtonsoftJson includes required converters for things like options (FsCodec.SystemTextJson has shims too, but those are a lot less necessary than they are for NSJ) Also if you want lots of features and dot mind taking a dep on a larger lib, look at FSharp.SystemTextJson

Thorium commented 7 months ago

I asked @eiriktsarpalis the best method for custom parsing json with System.Text.Json, he said:

just use Utf8JsonReader under wraps. That way make sure it's compliant and also take advantage of all the vectorization code it's using under the hood.

So I tried a bit: https://gist.github.com/Thorium/09a67ce08adee4fcc02ec7f0048e6962 That could work here as well.

bartelink commented 7 months ago

I should mention though - while GC and perf for STJ is in another league, ultimately the perf of JSON serialization is not make or break for 99% of systems. i.e. my motivations for mentioning other libs is not primarily based on perf, more:

Thorium commented 7 months ago

Fair point, however often JSON is used in data communications which often means there is either active user looking progress-bar, or there is a huge batch process going on, so speed is somewhat a property.

Beside the options you mentioned there is FSharp.Data.JsonProvider which is extremely convenient to use, having its own parser.

Right now I feel that F# eco-system has had this problem of everyone copy&pasting their own serialization implementations (and AI-tools will make this even easier in the future). And because everything is OSS, people also referencing single serialization-implementation files directly (e.g. paket files). That's why fixing old code is important even in old less-maintained sources.