Reduce array allocations during CompositeByteBuf construction

Motivation:

Eliminate avoidable backing array reallocations when constructing
composite ByteBufs from existing buffer arrays/Iterables. This also
applies to the Unpooled.wrappedBuffer(...) methods.

Modifications:

Ensure the initial components ComponentList is sized at least as large
as the provided buffer array/Iterable in the CompositeByteBuffer
constructors.

In single-arg Unpooled.wrappedBuffer(...) methods, set maxNumComponents
to the count of provided buffers, rather than a fixed default of 16. It
seems likely that most usage of these involves wrapping a list without
subsequent modification, particularly since they return a ByteBuf rather
than CompositeByteBuf. If a different/larger max is required there are
already the wrappedBuffer(int, ...) variants.

In fact the current behaviour could be considered inconsistent - if you
call Unpooled.wrappedBuffer(int, ByteBuf) with a single buffer, you
might expect to subsequently be able to add buffers to it (since you
specified a max related to consolidation), but it will in fact return
just a slice of the provided ByteBuf.

Result:

Fewer and smaller allocations in some cases when using CompositeByteBufs
or Unpooled.wrappedBuffer(...).
This commit is contained in:
nickhill 2018-06-20 00:13:09 -07:00 committed by Norman Maurer
parent b1d4b2af1c
commit 9b95b8ee62
2 changed files with 11 additions and 8 deletions

View File

@ -61,7 +61,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
this.alloc = alloc;
this.direct = direct;
this.maxNumComponents = maxNumComponents;
components = newList(maxNumComponents);
components = newList(0, maxNumComponents);
}
public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) {
@ -82,7 +82,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
this.alloc = alloc;
this.direct = direct;
this.maxNumComponents = maxNumComponents;
components = newList(maxNumComponents);
components = newList(len, maxNumComponents);
addComponents0(false, 0, buffers, offset, len);
consolidateIfNeeded();
@ -100,18 +100,21 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
"maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
}
int len = buffers instanceof Collection ? ((Collection<ByteBuf>) buffers).size() : 0;
this.alloc = alloc;
this.direct = direct;
this.maxNumComponents = maxNumComponents;
components = newList(maxNumComponents);
components = newList(len, maxNumComponents);
addComponents0(false, 0, buffers);
consolidateIfNeeded();
setIndex(0, capacity());
}
private static ComponentList newList(int maxNumComponents) {
return new ComponentList(Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents));
private static ComponentList newList(int initComponents, int maxNumComponents) {
int capacityGuess = Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents);
return new ComponentList(Math.max(initComponents, capacityGuess));
}
// Special constructor used by WrappedCompositeByteBuf

View File

@ -238,7 +238,7 @@ public final class Unpooled {
* content will be visible to the returned buffer.
*/
public static ByteBuf wrappedBuffer(byte[]... arrays) {
return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, arrays);
return wrappedBuffer(arrays.length, arrays);
}
/**
@ -249,7 +249,7 @@ public final class Unpooled {
* @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
*/
public static ByteBuf wrappedBuffer(ByteBuf... buffers) {
return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, buffers);
return wrappedBuffer(buffers.length, buffers);
}
/**
@ -258,7 +258,7 @@ public final class Unpooled {
* specified buffers will be visible to the returned buffer.
*/
public static ByteBuf wrappedBuffer(ByteBuffer... buffers) {
return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, buffers);
return wrappedBuffer(buffers.length, buffers);
}
/**