-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Reduce long[] array allocation for bitset in readBitSetIterator #13828
Conversation
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 left some minor comments, otherwise LGTM. Thanks @easyice !
@@ -36,6 +38,7 @@ final class DocIdsWriter { | |||
private static final byte LEGACY_DELTA_VINT = (byte) 0; | |||
|
|||
private final int[] scratch; | |||
private long[] scratchLongs = new long[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.
You can use LongsRef.EMPTY_LONGS
here.
long[] bits = new long[longLen]; | ||
in.readLongs(bits, 0, longLen); | ||
FixedBitSet bitSet = new FixedBitSet(bits, longLen << 6); | ||
if (longLen > scratchLongs.length) { |
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.
Do we need this comparison when growNoCopy
check this as well?
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.
It’s an interesting question, currently we have some places that perform the comparison before growNoCopy
and some that don't. In #13171, I found a slight performance impact regarding the extra assignment like scratchLongs = scratchLongs
. But indeed, keeping things simple is more important.
} | ||
in.readLongs(scratchLongs, 0, longLen); | ||
// make ghost bits clear | ||
Arrays.fill(scratchLongs, longLen, scratchLongs.length, 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.
Can we make scratchLongs a LongsRef
to know how many words we used last time, so that we can avoid this clear when unnecessary?
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. If the current longLen is greater than the previous value, we don’t need to perform the clear.
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.
LGTM, Thanks @easyice !
…or (apache#13828)" This reverts commit 50bf845.
I got a memory allocation flamegraph from my cluster, It shows the
DocIdsWriter#readBitSetIterator
allocating about ~14GB RAM in 30 seconds, this proposal uses ascratchLongs[]
array instead of allocating a new array.mem.html.zip
When using some mock data that let
DocIdsWriter#readBitSetIterator
allocate a long[] array of size 96, the JMH output shows:main:
pr:
JMH Code