Reduce Object allocations in CompositeByteBuf.
Motivation: We used subList in CompositeByteBuf to remove ranges of elements from the internal storage. Beside this we also used an foreach loop in a few cases which will crate an Iterator. Modifications: - Use our own sub-class of ArrayList which exposes removeRange(...). This allows to remove a range of elements without an extra allocation. - Use an old style for loop to iterate over the elements to reduce object allocations. Result: Less allocations.
This commit is contained in:
parent
63bae0956a
commit
1988cd041d
@ -48,7 +48,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
|
||||
private final ByteBufAllocator alloc;
|
||||
private final boolean direct;
|
||||
private final List<Component> components;
|
||||
private final ComponentList components;
|
||||
private final int maxNumComponents;
|
||||
|
||||
private boolean freed;
|
||||
@ -110,8 +110,8 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
setIndex(0, capacity());
|
||||
}
|
||||
|
||||
private static List<Component> newList(int maxNumComponents) {
|
||||
return new ArrayList<Component>(Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents));
|
||||
private static ComponentList newList(int maxNumComponents) {
|
||||
return new ComponentList(Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents));
|
||||
}
|
||||
|
||||
// Special constructor used by WrappedCompositeByteBuf
|
||||
@ -120,7 +120,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
this.alloc = alloc;
|
||||
direct = false;
|
||||
maxNumComponents = 0;
|
||||
components = Collections.emptyList();
|
||||
components = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -486,15 +486,16 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
if (numComponents == 0) {
|
||||
return this;
|
||||
}
|
||||
List<Component> toRemove = components.subList(cIndex, cIndex + numComponents);
|
||||
int endIndex = cIndex + numComponents;
|
||||
boolean needsUpdate = false;
|
||||
for (Component c: toRemove) {
|
||||
for (int i = cIndex; i < endIndex; ++i) {
|
||||
Component c = components.get(i);
|
||||
if (c.length > 0) {
|
||||
needsUpdate = true;
|
||||
}
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
toRemove.clear();
|
||||
components.removeRange(cIndex, endIndex);
|
||||
|
||||
if (needsUpdate) {
|
||||
// Only need to call updateComponentOffsets if the length was > 0
|
||||
@ -1557,7 +1558,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
c.freeIfNecessary();
|
||||
}
|
||||
|
||||
components.subList(cIndex + 1, endCIndex).clear();
|
||||
components.removeRange(cIndex + 1, endCIndex);
|
||||
components.set(cIndex, new Component(consolidated));
|
||||
updateComponentOffsets(cIndex);
|
||||
return this;
|
||||
@ -1576,8 +1577,9 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
// Discard everything if (readerIndex = writerIndex = capacity).
|
||||
int writerIndex = writerIndex();
|
||||
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
||||
for (Component c: components) {
|
||||
c.freeIfNecessary();
|
||||
int size = components.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
components.get(i).freeIfNecessary();
|
||||
}
|
||||
components.clear();
|
||||
setIndex(0, 0);
|
||||
@ -1590,7 +1592,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
for (int i = 0; i < firstComponentId; i ++) {
|
||||
components.get(i).freeIfNecessary();
|
||||
}
|
||||
components.subList(0, firstComponentId).clear();
|
||||
components.removeRange(0, firstComponentId);
|
||||
|
||||
// Update indexes and markers.
|
||||
Component first = components.get(0);
|
||||
@ -1612,8 +1614,9 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
// Discard everything if (readerIndex = writerIndex = capacity).
|
||||
int writerIndex = writerIndex();
|
||||
if (readerIndex == writerIndex && writerIndex == capacity()) {
|
||||
for (Component c: components) {
|
||||
c.freeIfNecessary();
|
||||
int size = components.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
components.get(i).freeIfNecessary();
|
||||
}
|
||||
components.clear();
|
||||
setIndex(0, 0);
|
||||
@ -1626,19 +1629,20 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
for (int i = 0; i < firstComponentId; i ++) {
|
||||
components.get(i).freeIfNecessary();
|
||||
}
|
||||
components.subList(0, firstComponentId).clear();
|
||||
|
||||
// Remove or replace the first readable component with a new slice.
|
||||
Component c = components.get(0);
|
||||
Component c = components.get(firstComponentId);
|
||||
int adjustment = readerIndex - c.offset;
|
||||
if (adjustment == c.length) {
|
||||
// new slice would be empty, so remove instead
|
||||
components.remove(0);
|
||||
firstComponentId++;
|
||||
} else {
|
||||
Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment));
|
||||
components.set(0, newC);
|
||||
components.set(firstComponentId, newC);
|
||||
}
|
||||
|
||||
components.removeRange(0, firstComponentId);
|
||||
|
||||
// Update indexes and markers.
|
||||
updateComponentOffsets(0);
|
||||
setIndex(0, writerIndex - readerIndex);
|
||||
@ -1972,4 +1976,17 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
throw new UnsupportedOperationException("Read-Only");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ComponentList extends ArrayList<Component> {
|
||||
|
||||
ComponentList(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
// Expose this methods so we not need to create a new subList just to remove a range of elements.
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
super.removeRange(fromIndex, toIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user