-
Notifications
You must be signed in to change notification settings - Fork 404
perf(crypto): simplify and speed up Address.Compare #4130
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
base: master
Are you sure you want to change the base?
perf(crypto): simplify and speed up Address.Compare #4130
Conversation
🛠 PR Checks SummaryAll Automated Checks passed. ✅ Manual Checks (for Reviewers):
Read More🤖 This bot helps streamline PR reviews by verifying automated checks and providing guidance for contributors and reviewers. ✅ Automated Checks (for Contributors):🟢 Maintainers must be able to edit this pull request (more info) ☑️ Contributor Actions:
☑️ Reviewer Actions:
📚 Resources:Debug
|
fcd6916
to
6e68708
Compare
6e68708
to
6b5b5ec
Compare
Codecov ReportAttention: Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
I can see that reduced memory copying and unnecessary repeated calls. It looks reasonable to me. approved 👍
remove: review/triage-pending
flag
Takes advantage of knowledge that Address is simply an array derived from []byte and Go's rules allow us to address each with [:] to find []byte and pass those into bytes.Compare instead of the unnecessarily inefficient make, copy. crypto.Address is very fundamental and a building block to Gno and all of cryptocurrencies, thus making its operations much more efficient is necessary. While here also made Address.Compare take a pointer receiver which reduces the need to make a stack copy of the receiver and with that we have this speed up while making the code more succinct and direct and more idiomatic ```shell $ benchstat before.txt after.txt name old time/op new time/op delta AddressCompare-8 79.5ns ± 1% 52.9ns ± 3% -33.54% (p=0.000 n=10+9) name old alloc/op new alloc/op delta AddressCompare-8 8.00B ± 0% 8.00B ± 0% ~ (all equal) name old allocs/op new allocs/op delta AddressCompare-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) ``` Fixes gnolang#4129
The updated benchmark then becomes ```shell name old time/op new time/op delta AddressCompare-8 79.5ns ± 1% 33.3ns ± 8% -58.17% (p=0.000 n=10+9) name old alloc/op new alloc/op delta AddressCompare-8 8.00B ± 0% 8.00B ± 0% ~ (all equal) name old allocs/op new allocs/op delta AddressCompare-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) ```
54af354
to
47e1195
Compare
I don't know if this matters enough; it seems to be used in some functions in Validator/ValidatorSet to matter enough. I'll let someone else take a second look first. |
I'm also skeptical about how much it matters. We should have not only "per function benchmarks" but also flame graphs that show how frequently calls are made in real usage. These flame graphs could become shared assets rather than something we expect with each pull request. I'll open an issue to explore if someone has a good idea for generating flame graphs in the CI. We don't need a history; ideally, we just want a few generated flame graphs that match a recent version of the code or a pull request for convenience. |
-> #4151 |
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.
Let's block this PR until we can compare a before-and-after using a usage flamegraph or another method that provides real-world usage data, not just per-function metrics.
One thing though to objectively acknowledge and note is that the prior code was really extraneous and my change isn't even an "optimization" but really how the code should have been written for idiomatic Go the proper way, it just happens to make the code much more efficient and faster. Skepticism over performance is usually more pertinent when one is being clever and the performance checks will later show, Address comparison is pretty important and quite heavily used. |
Let's prove it. |
Takes advantage of knowledge that Address is simply an array derived from []byte and Go's rules allow us to address each with [:] to find []byte and pass those into bytes.Compare instead of the unnecessarily inefficient make, copy. crypto.Address is very fundamental and a building block to Gno and all of cryptocurrencies, thus making its operations much more efficient is necessary.
While here also made Address.Compare take a pointer receiver which reduces the need to make a stack copy of the receiver and with that we have this speed up while making the code more succinct and direct and more idiomatic
Fixes #4129