-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Faster bucket search in ByteBufferHashTable #18952
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
Faster bucket search in ByteBufferHashTable #18952
Conversation
|
Thanks! Can we include a performance test (see |
|
Sorry, I accidentally broke the empty bucket check with the earlier commit - fixed it in 2d9520f. Also updated the benchmark results with the measurements obtained on the latest commit. |
gianm
left a comment
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.
The changes look good to me. Thank you for including a benchmark as well.
jtuglu1
left a comment
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.
Thank you! Left 2 small, non-blocking comments.
| final int storedHashWithUsedFlag = targetTableBuffer.getInt(bucketOffset); | ||
|
|
||
| if ((targetTableBuffer.get(bucketOffset) & 0x80) == 0) { | ||
| if ((storedHashWithUsedFlag & 0x80000000) == 0) { |
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.
nit: while we're here, can we name this mask? It's used in other places below (byte-level mask) and makes it easier to read potentially.
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.
Addressed in 5fb014f
| ) | ||
| { | ||
| // Compare 8 bytes at a time | ||
| while (length >= Long.BYTES) { |
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.
Maybe we can save a comparison by switching to a do/while loop since I believe length will always be ≥ 8. This likely will not show up in the benchmark, however. Unfortunately we cannot do something like [[likely]] in Java I don't think.
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'd rather keep the method correct in the face of smaller keys, if this ever changes in the future. Also, if the keys are always >=8, the first branch will be always taken, so CPU's branch predictor should make it very cheap.
|
@puzpuzpuz Thanks for the change. I'm wondering how much does this change improve(like the CPU usage) in a real cluster? |
This is a small change and unlikely it's a significant bottleneck in typical workloads, but I'm guessing here. BTW are there any public benchmarks in which Druid actively participates? If so, it's a good idea to check those to be able to make more educated optimizations (if any required/possible). |
Description
Adds hash code comparison for large enough keys to
ByteBufferHashTable#findBucket(). Also, changes key comparison to use long/int/byte instead of byte-only comparison (thus, the comparison is now closer toHashTableUtils#memoryEquals()used inMemoryOpenHashTable). These changes are aimed to speed-up bucket search inByteBufferHashTable, especially in high-collision cases.Microbenchmarks
Environment: Ryzen 7900x, Ubuntu 24.04, OpenJDK 64-bit 17.0.17
Before:
After:
Release note
Speed-up bucket search in hash table used by GROUP BY
Key changed/added classes in this PR
ByteBufferHashTableThis PR has: