-
Notifications
You must be signed in to change notification settings - Fork 28.9k
[SPARK-7251] Perform sequential scan when iterating over BytesToBytesMap #6159
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
|
Merged build triggered. |
|
Merged build started. |
|
Test build #32737 has started for PR 6159 at commit |
|
Here's some benchmark code which builds a map with millions of records that have random 64-byte keys and values, then repeatedly iterates over the map and copies the keys and values into byte arrays: https://gist.github.com/JoshRosen/286b26494ab27e657051 For this benchmark, I saw a nearly 10x improvement as a result of this patch. |
|
Test build #32737 has finished for PR 6159 at commit
|
|
Merged build finished. Test PASSed. |
|
Test PASSed. |
|
/cc @rxin for review. |
|
@zsxwing can you take a look at this one as well? |
|
@JoshRosen could you explain what will happen if |
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 current implementation does not follow the javadoc of Iterator: @throws NoSuchElementException if the iteration has no more elements. However, it may be fine since it's an internal API.
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.
If we decide to do this, there's other places where we should also perform the same change. I'd like to defer this decision for now and deal with it in a follow up patch that makes the change more broadly.
|
How about make BytesToBytesMap implement |
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.
Could you also add a test to iterate an empty BytesToBytesMap?
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.
Good idea. I'll fold this into the emptyMap() test at the start of this file.
|
@zsxwing, nice catch RE: the risk of overflow when growing the map. This is a really hard-to-hit corner-case, but it's still worth fixing. I'll address this shortly. |
|
I'm adding a test for the overflow and noticed something interesting: when we overflow to |
|
Ah, I see now that it has to be at least 64 so that the division when sizing the bitset is safe. I'll leave a comment explaining this. |
|
While fixing this, I found a units / sizing issue: our |
|
Merged build triggered. |
|
Merged build started. |
|
Test build #33030 has started for PR 6159 at commit |
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.
MAX_CAPACITY should be (1 << 30) - 1.
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 hashtable has to be power-of-2-sized. Our long array can have at most (1 << 30) elements, since that's the largest power-of-2 that's less than Integer.MAX_VALUE, but we need two long array entries per record, so that gives us a maximum capacity of (1 << 29).
|
Test build #33030 has finished for PR 6159 at commit
|
|
Merged build finished. Test PASSed. |
|
Test PASSed. |
|
Merged build triggered. |
|
Merged build started. |
|
Test build #33100 has started for PR 6159 at commit |
|
Test build #33100 has finished for PR 6159 at commit
|
|
Merged build finished. Test PASSed. |
|
Test PASSed. |
|
LGTM |
|
Thanks for the review. I'm going to merge this into master and branch-1.4 (1.4.0). |
This patch modifies `BytesToBytesMap.iterator()` to iterate through records in the order that they appear in the data pages rather than iterating through the hashtable pointer arrays. This results in fewer random memory accesses, significantly improving performance for scan-and-copy operations. This is possible because our data pages are laid out as sequences of `[keyLength][data][valueLength][data]` entries. In order to mark the end of a partially-filled data page, we write `-1` as a special end-of-page length (BytesToByesMap supports empty/zero-length keys and values, which is why we had to use a negative length). This patch incorporates / closes #5836. Author: Josh Rosen <[email protected]> Closes #6159 from JoshRosen/SPARK-7251 and squashes the following commits: 05bd90a [Josh Rosen] Compare capacity, not size, to MAX_CAPACITY 2a20d71 [Josh Rosen] Fix maximum BytesToBytesMap capacity bc4854b [Josh Rosen] Guard against overflow when growing BytesToBytesMap f5feadf [Josh Rosen] Add test for iterating over an empty map 273b842 [Josh Rosen] [SPARK-7251] Perform sequential scan when iterating over entries in BytesToBytesMap (cherry picked from commit f2faa7a) Signed-off-by: Josh Rosen <[email protected]>
This patch modifies `BytesToBytesMap.iterator()` to iterate through records in the order that they appear in the data pages rather than iterating through the hashtable pointer arrays. This results in fewer random memory accesses, significantly improving performance for scan-and-copy operations. This is possible because our data pages are laid out as sequences of `[keyLength][data][valueLength][data]` entries. In order to mark the end of a partially-filled data page, we write `-1` as a special end-of-page length (BytesToByesMap supports empty/zero-length keys and values, which is why we had to use a negative length). This patch incorporates / closes apache#5836. Author: Josh Rosen <[email protected]> Closes apache#6159 from JoshRosen/SPARK-7251 and squashes the following commits: 05bd90a [Josh Rosen] Compare capacity, not size, to MAX_CAPACITY 2a20d71 [Josh Rosen] Fix maximum BytesToBytesMap capacity bc4854b [Josh Rosen] Guard against overflow when growing BytesToBytesMap f5feadf [Josh Rosen] Add test for iterating over an empty map 273b842 [Josh Rosen] [SPARK-7251] Perform sequential scan when iterating over entries in BytesToBytesMap
This patch modifies `BytesToBytesMap.iterator()` to iterate through records in the order that they appear in the data pages rather than iterating through the hashtable pointer arrays. This results in fewer random memory accesses, significantly improving performance for scan-and-copy operations. This is possible because our data pages are laid out as sequences of `[keyLength][data][valueLength][data]` entries. In order to mark the end of a partially-filled data page, we write `-1` as a special end-of-page length (BytesToByesMap supports empty/zero-length keys and values, which is why we had to use a negative length). This patch incorporates / closes apache#5836. Author: Josh Rosen <[email protected]> Closes apache#6159 from JoshRosen/SPARK-7251 and squashes the following commits: 05bd90a [Josh Rosen] Compare capacity, not size, to MAX_CAPACITY 2a20d71 [Josh Rosen] Fix maximum BytesToBytesMap capacity bc4854b [Josh Rosen] Guard against overflow when growing BytesToBytesMap f5feadf [Josh Rosen] Add test for iterating over an empty map 273b842 [Josh Rosen] [SPARK-7251] Perform sequential scan when iterating over entries in BytesToBytesMap
This patch modifies `BytesToBytesMap.iterator()` to iterate through records in the order that they appear in the data pages rather than iterating through the hashtable pointer arrays. This results in fewer random memory accesses, significantly improving performance for scan-and-copy operations. This is possible because our data pages are laid out as sequences of `[keyLength][data][valueLength][data]` entries. In order to mark the end of a partially-filled data page, we write `-1` as a special end-of-page length (BytesToByesMap supports empty/zero-length keys and values, which is why we had to use a negative length). This patch incorporates / closes apache#5836. Author: Josh Rosen <[email protected]> Closes apache#6159 from JoshRosen/SPARK-7251 and squashes the following commits: 05bd90a [Josh Rosen] Compare capacity, not size, to MAX_CAPACITY 2a20d71 [Josh Rosen] Fix maximum BytesToBytesMap capacity bc4854b [Josh Rosen] Guard against overflow when growing BytesToBytesMap f5feadf [Josh Rosen] Add test for iterating over an empty map 273b842 [Josh Rosen] [SPARK-7251] Perform sequential scan when iterating over entries in BytesToBytesMap
This patch modifies
BytesToBytesMap.iterator()to iterate through records in the order that they appear in the data pages rather than iterating through the hashtable pointer arrays. This results in fewer random memory accesses, significantly improving performance for scan-and-copy operations.This is possible because our data pages are laid out as sequences of
[keyLength][data][valueLength][data]entries. In order to mark the end of a partially-filled data page, we write-1as a special end-of-page length (BytesToByesMap supports empty/zero-length keys and values, which is why we had to use a negative length).This patch incorporates / closes #5836.