-
Notifications
You must be signed in to change notification settings - Fork 919
Optimize base58 on small inputs #3002
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
Conversation
Pull Request Test Coverage Report for Build 9885605832Details
💛 - Coveralls |
|
I confirm I see the ~4% improvement (~5% on my machine) ACK 56759ecc672f25c03f6279b0fb7aae52e50ef8ed I just have the following doubt, if I understand correctly the ArrayVec is never resizing but we use it because it offers the ergonomics of push and length tracking but we could use a plain array instead? Most probably same performance and would have a more complex |
Correct.
That and also the management of
Of course,
I don't think this is worth pursuing. All solutions I can come up with either have extra assumptions (only known lengths) or require insane complexity beyond what the |
|
I think the Although if you need to change it, there are a couple lines of whitespace added in this diff that you could remove. |
Most base58 strings in Bitcoin are somewhat short. There was previously an "optimization" putting part of the input on stack which was removed in rust-bitcoin#2759 because it actually made the code slower. This appears to be mostly because of branches caused by using `iter::Chain`. Manually splitting the iterations into two helped bring the performance close to what rust-bitcoin#2759 achieved but that still wasn't worth it. But given that we know the input length in many cases (it's just a slice) we can determine whether it'll fit a buffer upfront and then just call different functions which don't have the branches in loops. To avoid having two functions this uses generics instead. Further, we increase the buffer length to 128 and use `ArrayVec` from `internals` which internally avoids initializing the buffer thanks to `MaybeUninit` In total this increases performance by around 4% on my machine.
|
I've removed the whitespace and fixed a grammar error in the commit message. |
|
Also I had an idea how to make no-alloc One thing that I'm thinking about though is that currently passing a string effectively creates two buffers and copies between them. We could instead try to reuse the buffer and avoid copies. The hard part is figuring out a good API and preferably a way to do it without |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK d05723c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK d05723c
Most base58 strings in Bitcoin are somewhat short. There was previously an "optimization" putting part of the input on stack which was removed in #2759 because it actually made the code slower. This appears to be mostly because of branches caused by using
iter::Chain.Manually splitting the iterations into two helped bring the performance close to what #2759 achieved but that still wasn't worth it. But given that we know the input length in many cases (it's just a slice) we can determine whether it'll fit a buffer upfront and then just call different functions which don't have the branches in loops. To avoid having two functions this uses generics instead. Further, we increase the buffer length to 128 and use
ArrayVecfrominternalswhich internally avoids initializing the buffer thanks toMaybeUninitIn total this increases performance by around 4% on my machine.