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
273 stars 55 forks source link

Binary serialization with MsgPack #158

Closed kerams closed 4 years ago

kerams commented 4 years ago

Aiming to implement binary serialization of API responses using Message Pack.

Once complete, it should support the same types as Fable.Remoting.Json while offering better (de)serialization performance and smaller payloads.

Supported types

TODO

Anything I've missed?

kerams commented 4 years ago

@Zaid-Ajaj, I'm in sight of the finish line. Are you in favor of the proposed API? I.e. adding |> withBinarySerialization when creating the proxy and server handlers?

Zaid-Ajaj commented 4 years ago

It looks really amazing 😍 :heart: The API looks good too and especially easy to start using once people update their adapters to the new version.

The only thing that might be missing is checking whether Fable.Remoting.DotnetClient works like it should with the binary protocol which also uses Fable.Remoting.Json for the data transport

kerams commented 4 years ago

The only thing that might be missing is checking whether Fable.Remoting.DotnetClient works like it should with the binary protocol

Right, the same goes for Giraffe.

kerams commented 4 years ago

Do you have any experience with performance tests under Fable by any chance? I've done some benchmarks of deserialization on .NET, and while the results are not too bad, they won't reflect Javascript performance.


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.329 (2004/?/20H1)
AMD Ryzen 7 3700X, 1 CPU, 16 logical and 8 physical cores
.NET Core SDK=5.0.100-preview.8.20351.5
  [Host]     : .NET Core 3.1.2 (CoreCLR 4.700.20.6602, CoreFX 4.700.20.6702), X64 RyuJIT DEBUG
  DefaultJob : .NET Core 3.1.2 (CoreCLR 4.700.20.6602, CoreFX 4.700.20.6702), X64 RyuJIT
  Job-SXWUEH : .NET Core 3.1.2 (CoreCLR 4.700.20.6602, CoreFX 4.700.20.6702), X64 RyuJIT

InvocationCount=1  
Type Method Job UnrollFactor Mean Error StdDev Median Gen 0 Gen 1 Gen 2 Allocated
Int64ArrayDeserialization Json DefaultJob 16 37.91 ms 0.131 ms 0.123 ms 37.92 ms 2000.0000 142.8571 71.4286 18.03 MB
Int64ArrayDeserialization MsgPack Job-VVPEKY 1 10.84 ms 0.151 ms 0.133 ms 10.88 ms - - - 8.39 MB
Int64ArraySerialization Json DefaultJob 16 56.42 ms 0.649 ms 0.608 ms 56.19 ms 5000.0000 1000.0000 - 47.71 MB
Int64ArraySerialization MsgPack DefaultJob 16 15.21 ms 0.112 ms 0.104 ms 15.22 ms 359.3750 62.5000 62.5000 4.29 MB
IntMaybeMapDeserialization Json DefaultJob 16 705.69 ms 4.656 ms 3.888 ms 706.33 ms 35000.0000 9000.0000 - 286.04 MB
IntMaybeMapDeserialization MsgPack Job-VVPEKY 1 35.71 ms 0.710 ms 1.895 ms 34.74 ms 2000.0000 1000.0000 - 22.67 MB
IntMaybeMapSerialization Json DefaultJob 16 232.29 ms 0.547 ms 0.512 ms 232.40 ms 9000.0000 1000.0000 - 76.1 MB
IntMaybeMapSerialization MsgPack DefaultJob 16 15.16 ms 0.219 ms 0.205 ms 15.08 ms 984.3750 281.2500 31.2500 8.55 MB
RecursiveRecordDeserialization Json DefaultJob 16 1,045.86 ms 10.316 ms 9.649 ms 1,043.33 ms 55000.0000 12000.0000 - 438.84 MB
RecursiveRecordDeserialization MsgPack Job-VVPEKY 1 541.63 ms 3.090 ms 2.413 ms 540.80 ms 26000.0000 9000.0000 - 209.36 MB
RecursiveRecordSerialization Json DefaultJob 16 570.48 ms 5.563 ms 5.204 ms 569.12 ms 30000.0000 9000.0000 1000.0000 271.83 MB
RecursiveRecordSerialization MsgPack DefaultJob 16 518.65 ms 1.895 ms 1.680 ms 519.25 ms 19000.0000 - - 173.21 MB
Zaid-Ajaj commented 4 years ago

while the results are not too bad

LOL, "not bad" you say?! These benchmarks are INSANE 🀯 🀯

Do you have any experience with performance tests under Fable by any chance?

A while ago, I made a Fable project to test perf improvements in SimpleJson that is actually a unit test project with Mocha. When you run the tests in there, mocha shows you how long the test took so you can use that as a way to benchmark. I know it is not as fully-featured as with the .NET way but it should work OK-ish.

I believe this PR is ready to go? πŸ˜‰

kerams commented 4 years ago

I believe this PR is ready to go? πŸ˜‰

Yeah. Would be great if you could make a prerelease so that I can dogfood it and fix any issues.

it is not as fully-featured

I see what you mean. Should be sufficient for some ballpark numbers though.

Zaid-Ajaj commented 4 years ago

Packages are up :rocket: πŸš€ πŸš€

2020-07-04 21_49_16-Zaid-Ajaj_Fable Remoting_ Type-safe communication layer (RPC-style) for F# featu

I didn't bother with a prerelease version, I trust the integration tests :smile: do you wanna give it a try before I tweet this awesomeness? :wink:

kerams commented 4 years ago

Trying it right now. I think the new Nuget package is missing the source files.

Zaid-Ajaj commented 4 years ago

Which one of them. the Fable.Remoting.Client?

Edit: I see the issue now, source files of Fable.Remoting.MsgPack weren't published. Fixes the issue, it should be good now if you update Fable.Remoting.Client from 6.0.0 to 6.0.1

kerams commented 4 years ago

Tried it on one API endpoint and so far so good, no errors :). Message Pack without compression appears to produce slightly larger messages than JSON + Brotli in some cases, but when I enable it, the former has the upper hand.

Zaid-Ajaj commented 4 years ago

Do you think we should add docs to ensure compression in enabled when using msgpack?

kerams commented 4 years ago

Not sure if it's strictly necessary if this is almost as good as JSON with compression while using fewer CPU cycles. Besides, it's a little complicated here since in ASP.NET compression is enabled based on MIME types and responses with Message Pack use octet-stream (just like static files that you don't want to compress, such as images). I suppose the MIME type could be changed to something else to allow for better compression control.