irmen / Pyrolite

Java and .NET client interface for Pyro5 protocol
MIT License
177 stars 47 forks source link

Improve unpickling performance when reading from memory buffer #64

Closed adamsitnik closed 5 years ago

adamsitnik commented 5 years ago

When the Unpickler reads from a Stream it has non-trivial overhead compared to when reading from a memory buffer. This PR improves unpickling performance for that case.

The difference

Perf trick: the types that implement IInputReader are structs to enable for full interface method devirtualization and inlining. You can read about it here. I have added the necessary comment in the code that explains that.

The gains are quite big. From 20% to 2 times faster when unpickling from array. Unpickling from Stream has not been regressed. I added micro-benchmarks to measure and ensure this.

Method Count WAS IS netcoreapp2.0 IS netcoreapp3.0
DoublesFromStream 100 7.151 us 7.174 us 5.594 us
IntegersFromStream 100 4.859 us 4.427 us 4.240 us
BooleansFromStream 100 2.183 us 1.917 us 1.824 us
StringsFromStream 100 14.648 us 12.766 us 10.439 us
DoublesFromArray 100 7.246 us 5.020 us 3.912 us
IntegersFromArray 100 4.802 us 3.897 us 3.822 us
BooleansFromArray 100 2.154 us 1.653 us 1.626 us
StringsFromArray 100 13.254 us 9.353 us 7.298 us
DoublesFromStream 1000 61.817 us 60.708 us 48.213 us
IntegersFromStream 1000 52.808 us 50.321 us 39.714 us
BooleansFromStream 1000 18.297 us 15.809 us 14.560 us
StringsFromStream 1000 151.480 us 142.836 us 112.647 us
DoublesFromArray 1000 60.844 us 41.348 us 31.345 us
IntegersFromArray 1000 52.648 us 40.204 us 31.525 us
BooleansFromArray 1000 18.346 us 13.245 us 13.369 us
StringsFromArray 1000 153.078 us 99.069 us 72.801 us

/cc @stephentoub, @imback82, @eerhardt, @rapoth

irmen commented 5 years ago

I have been on holiday so haven't been able to follow this PR until now. Will have a look at all the stuff that was talked about tomorrow, I think

adamsitnik commented 5 years ago

@irmen I have pushed all the code fixes, the code is ready for review.

irmen commented 5 years ago

I hope to be able to review all this in the following few days, but it's clear to me that you guys are a lot more knowledgeable about these low level optimizations than I am. So I don't think I'll be able to comment on the function, but rather only on the form (if any)

irmen commented 5 years ago

thanks a lot for these PRs and it's exiting that it makes Pyrolite a key library in .NET Spark

adamsitnik commented 5 years ago

@irmen thank you for the awesome library!

BTW please don't release a new NuGet package yet, tomorrow I plan to finish a PR that improves the Pickler performance.

Preview:

Method Count Mean WAS Mean IS WAS Alloc IS Allocated
DoublesToByteArray 100 3.138 us 0.911 us 3184 B 304 B
StringsToByteArray 100 22.235 us 16.828 us 16424 B 10280 B
DoublesToByteArray 1000 31.298 us 7.269 us 42105 B 304 B
StringsToByteArray 1000 234.243 us 169.381 us 180100 B 102306 B
irmen commented 5 years ago

@adamsitnik Those are incredible results! I'm very curious what wizardry you're performing here

I'm just in the process right now of spicing up the readme.