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

Bincode 2 performance tracking #618

Open
JojiiOfficial opened this issue Feb 18, 2023 · 2 comments
Open

Bincode 2 performance tracking #618

JojiiOfficial opened this issue Feb 18, 2023 · 2 comments

Comments

@JojiiOfficial
Copy link

JojiiOfficial commented Feb 18, 2023

I was curious whether v2 brings performance improvements as it doesn't rely on serde. So I decided to do a quick criterion benchmark and was kinda surprised when I saw the results.
As you can see on the screenshot below encoding is around 100x slower than v1 and decoding around 5-8x slower. I'm personally using bincode over other formats as I don't need human readable (de)serialization of my data but rather want it to be as fast as possible as my entire applications performance depends on it. So it would be nice if v2 doesn't have these performance drawbacks. Of course one could continue use the serde implementation (although I haven't tested the performance of serde in v2) but such a performance drawback in a crate like bincode should be considered as bug in my opinion, so I created this issue.
You can find the code here: https://github.com/JojiiOfficial/bincode_bench

image

@VictorKoenders
Copy link
Contributor

Turning on [profile.bench] lto = true in the Cargo.toml massively increases the performance. In initial testing we found bincode-2 to be 10-20% faster, but it looks like this is no longer the case

image

My guess is that we should add more [inline] attributes to functions

@VictorKoenders
Copy link
Contributor

Bincode 1 essentially does &[u8].to_vec(): https://github.com/bincode-org/bincode/blob/v1.x/src/de/read.rs#L126-L128

Bincode 2 aims to be usable in no_std, so it only provides an interface to fill a &mut [u8]: https://github.com/bincode-org/bincode/blob/trunk/src/de/read.rs#L19

Because of this, in bincode 2 we have to do

let mut vec = vec![0u8; len];
reader.read(&mut vec); // essentially `vec.copy_from_slice(&[u8]);`

Where in bincode 1 we could do

let vec = reader.read_vec()?; // essentially `&[u8].to_vec()`

Which is why bincode 1 is 20% faster in this specific case.

Funnily enough after #667 reading Vec<u8> is about 5 times faster in bincode 2, because we can optimize Vec<T> where T: u8 to read the entire buffer instead of byte-by-byte. But in bincode 1 the string one is slightly more optimized.

One possible solution is to have the reader be able to optimize for &mut [MaybeUninit<u8>]. It seems like rust is working on a feature called read_buf which provides a nice interface over this. Tracking issue 78485. Once this is stable, bincode can opt into this to improve String decoding speed. Initial estimates seem to indicate bincode 2 will be 10% faster than bincode 1 with this new interface.

@VictorKoenders VictorKoenders changed the title Bincode 2 is 10-100x slower than Bincode 1 when Encoding Bincode 2 performance tracking Sep 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants