Skip to content
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 ByteBuffer duplication when resizing pooled direct ByteBufs #9765

Merged
merged 1 commit into from
Nov 16, 2019

Conversation

njhill
Copy link
Member

@njhill njhill commented Nov 8, 2019

Motivation

Currently when use of Unsafe is disabled and an internal reallocation is performed for a direct PooledByteBuf, a one-off temporary duplicate is made of the source and destination backing nio buffers so that the copy can be done in a threadsafe manner.

The need for this can be reduced by sharing the temporary duplicate buffer that is already stored in the corresponding destination PooledByteBuf instance.

Modifications

Have PoolArena#memoryCopy(...) take the destination PooledByteBuf instead of the underlying mem reference and offset, and use internalNioBuffer() to obtain/initialize a reusable duplicate of the
backing nio buffer.

Result

Fewer temporary allocations when resizing direct pooled ByteBufs in the non-Unsafe case

@netty-bot
Copy link

Can one of the admins verify this patch?

@normanmaurer
Copy link
Member

@netty-bot test this please

@normanmaurer normanmaurer added this to the 4.1.44.Final milestone Nov 8, 2019
@normanmaurer normanmaurer self-requested a review November 8, 2019 08:13
@@ -402,7 +402,9 @@ void reallocate(PooledByteBuf<T> buf, int newCapacity, boolean freeOldMemory) {
buf.trimIndicesToCapacity(newCapacity);
bytesToCopy = newCapacity;
}
memoryCopy(oldMemory, oldOffset, buf.memory, buf.offset, bytesToCopy);
if (bytesToCopy > 0) {
oldNioBuffer = memoryCopy(oldMemory, oldNioBuffer, oldOffset, buf, bytesToCopy);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm is this really correct ? This may now be duplicate that is passed to free(...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@normanmaurer the oldNioBuffer passed there is already a duplicate (comes from buf.tmpNioBuf) and isn't free'd itself, rather kept in the cache for later re-use by other ByteBufs that share the same "root" nio buffer...

@normanmaurer
Copy link
Member

@njhill honestly I wonder if this change really worth it... I mean it makes things more complex and resizing should be "hopefully" not happen too often. Or I am missing anything ?

@njhill
Copy link
Member Author

njhill commented Nov 11, 2019

@normanmaurer that's a fair point... I noticed this while looking closer at the underlying buffer manipulation done in ByteToMessageDecoder cumulation but you are probably right re the relative frequency not being big high to matter. Let me remove the "more complex" half of the change ... the other part is a slight simplification if anything imho

@normanmaurer
Copy link
Member

@netty-bot test this please

@normanmaurer
Copy link
Member

@njhill can you update the commit message and pr description to match what you did now ?

Motivation

Currently when use of Unsafe is disabled and an internal reallocation is
performed for a direct PooledByteBuf, a one-off temporary duplicate is
made of the source and destination backing nio buffers so that the
copy can be done in a threadsafe manner.

The need for this can be reduced by sharing the temporary duplicate
buffer that is already stored in the corresponding destination
PooledByteBuf instance.

Modifications

Have PoolArena#memoryCopy(...) take the destination PooledByteBuf
instead of the underlying mem reference and offset, and use
internalNioBuffer() to obtain/initialize a reusable duplicate of the
backing nio buffer.

Result

Fewer temporary allocations when resizing direct pooled ByteBufs in the
non-Unsafe case
@njhill
Copy link
Member Author

njhill commented Nov 13, 2019

@normanmaurer done

@normanmaurer
Copy link
Member

@netty-bot test this please

@normanmaurer normanmaurer merged commit b0feb5a into netty:4.1 Nov 16, 2019
@normanmaurer
Copy link
Member

@njhill thanks.. and sorry for the delay.

normanmaurer pushed a commit that referenced this pull request Nov 16, 2019
…9765)

Motivation:

Currently when use of Unsafe is disabled and an internal reallocation is
performed for a direct PooledByteBuf, a one-off temporary duplicate is
made of the source and destination backing nio buffers so that the
copy can be done in a threadsafe manner.

The need for this can be reduced by sharing the temporary duplicate
buffer that is already stored in the corresponding destination
PooledByteBuf instance.

Modifications:

Have PoolArena#memoryCopy(...) take the destination PooledByteBuf
instead of the underlying mem reference and offset, and use
internalNioBuffer() to obtain/initialize a reusable duplicate of the
backing nio buffer.

Result:

Fewer temporary allocations when resizing direct pooled ByteBufs in the
non-Unsafe case
@njhill njhill deleted the less-niobuf-dups branch November 16, 2019 21:03
njhill added a commit to njhill/netty that referenced this pull request Dec 30, 2019
Motivation

Recent optimization netty#9765 introduced a bug where the native indices of
the internal reused duplicate nio buffer are not properly reset prior to
using it to copy data during a reallocation operation. This can result
in BufferOverflowExceptions thrown during ByteBuf capacity changes.

The code path in question applies only to pooled direct buffers when
Unsafe is disabled or not available.

Modification

Ensure ByteBuffer#clear() is always called on the reused internal nio
buffer prior to returning it from PooledByteBuf#internalNioBuffer()
(protected method); add unit test that exposes the bug.

Result

Fixes netty#9911
normanmaurer pushed a commit that referenced this pull request Jan 11, 2020
…ize (#9912)


Motivation

Recent optimization #9765 introduced a bug where the native indices of
the internal reused duplicate nio buffer are not properly reset prior to
using it to copy data during a reallocation operation. This can result
in BufferOverflowExceptions thrown during ByteBuf capacity changes.

The code path in question applies only to pooled direct buffers when
Unsafe is disabled or not available.

Modification

Ensure ByteBuffer#clear() is always called on the reused internal nio
buffer prior to returning it from PooledByteBuf#internalNioBuffer()
(protected method); add unit test that exposes the bug.

Result

Fixes #9911
normanmaurer pushed a commit that referenced this pull request Jan 11, 2020
…ize (#9912)


Motivation

Recent optimization #9765 introduced a bug where the native indices of
the internal reused duplicate nio buffer are not properly reset prior to
using it to copy data during a reallocation operation. This can result
in BufferOverflowExceptions thrown during ByteBuf capacity changes.

The code path in question applies only to pooled direct buffers when
Unsafe is disabled or not available.

Modification

Ensure ByteBuffer#clear() is always called on the reused internal nio
buffer prior to returning it from PooledByteBuf#internalNioBuffer()
(protected method); add unit test that exposes the bug.

Result

Fixes #9911
ihanyong pushed a commit to ihanyong/netty that referenced this pull request Jul 31, 2020
…ize (netty#9912)


Motivation

Recent optimization netty#9765 introduced a bug where the native indices of
the internal reused duplicate nio buffer are not properly reset prior to
using it to copy data during a reallocation operation. This can result
in BufferOverflowExceptions thrown during ByteBuf capacity changes.

The code path in question applies only to pooled direct buffers when
Unsafe is disabled or not available.

Modification

Ensure ByteBuffer#clear() is always called on the reused internal nio
buffer prior to returning it from PooledByteBuf#internalNioBuffer()
(protected method); add unit test that exposes the bug.

Result

Fixes netty#9911
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants