Zaid-Ajaj / Fable.Remoting

Type-safe communication layer (RPC-style) for F# featuring Fable and .NET Apps
https://zaid-ajaj.github.io/Fable.Remoting/
MIT License
272 stars 54 forks source link

Implement reflection cache for unions, tuples, options and maps #254

Closed bklop closed 3 years ago

bklop commented 3 years ago

Hi Zaid! I recently identified a performance issue when serializing one of our F# domain models. The performance issue was caused by many repeated reflection calls at runtime in the FableConverter.

The "worst case" seems to be large DUs as keys in a Map, with many items in the Map. Our model looks something like this:

type MyUnion =
    | Case1
    | Case2
    ...
    | Case200

type MyRecord {
    Map1: Map<MyUnion, string>
    Map2: Map<MyUnion, string>
    ...
    Map20: Map<MyUnion, string> }

I've made some performance improvements which basically boil down to:

For our domain model (basically the code structure mentioned above) we saw serialization time decrease from 450ms to 1.5ms, which we're pretty happy with!

Zaid-Ajaj commented 3 years ago

This is really cool @bklop 🔥 the code looks good too!

Will try to merge and publish soon 😄

bklop commented 3 years ago

Thanks! But take your time to review it for correctness 😄. I tested it on a proprietary application + I made sure all tests pass (obviously).

Zaid-Ajaj commented 3 years ago

I made a benchmark project just for this, check it out here

The performance is insane 🔥 🔥 🔥

I made a large union (500 cases) and a large record (200 fields of type Map<LargeUnion, string>) and tested the JSON handling against the current JSON library and your implementation:

$ dotnet run
Running operations 10 time(s)
Old (Serialization): 2335L ms on average
New (Serialization): 425L ms on average
Old (Deserialization): 87517L ms on average
New (Deserialization): 4L ms on average
Old (Full convertion): 81919L ms on average
New (Full convertion): 2L ms on average
Zaid-Ajaj commented 3 years ago

PR merged and has been published into Fable.Remoting.Json v2.17 and all downstream packages that depend on it. Thanks a lot @bklop for the awesome contribution ❤️