Skip to content

Commit ec9875d

Browse files
Optimize method PoolChunk.allocate(...) to reduce overhead (#13528)
Motivation: When goes into method `PoolChunk.allocate(...)`, we need to check whether `head.next == head`, it has been checked before in method `PoolArena.tcacheAllocateSmall(...)`, but `head.next` may have been changed after that, so it needs to be checked again. This can lower the chance to call `PoolChunk.allocateSubpage(...)` and `PoolChunk.allocateRun(...)`, so will reduce overhead. Modification: Check whether `head.next == head` in method `PoolChunk.allocate(...)`. Result: Lower the chance of calling `PoolChunk.allocateSubpage(...)` and `PoolChunk.allocateRun(...)` to reduce overhead. Co-authored-by: laosijikaichele <laosijikaichele>
1 parent 5cb4974 commit ec9875d

1 file changed

Lines changed: 40 additions & 28 deletions

File tree

buffer/src/main/java/io/netty/buffer/PoolChunk.java

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,31 @@ private int usage(int freeBytes) {
314314
boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int sizeIdx, PoolThreadCache cache) {
315315
final long handle;
316316
if (sizeIdx <= arena.smallMaxSizeIdx) {
317+
final PoolSubpage<T> nextSub;
317318
// small
318-
handle = allocateSubpage(sizeIdx);
319-
if (handle < 0) {
320-
return false;
319+
// Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it.
320+
// This is need as we may add it back and so alter the linked-list structure.
321+
PoolSubpage<T> head = arena.findSubpagePoolHead(sizeIdx);
322+
head.lock();
323+
try {
324+
nextSub = head.next;
325+
if (nextSub != head) {
326+
assert nextSub.doNotDestroy && nextSub.elemSize == arena.sizeIdx2size(sizeIdx) : "doNotDestroy=" +
327+
nextSub.doNotDestroy + ", elemSize=" + nextSub.elemSize + ", sizeIdx=" + sizeIdx;
328+
handle = nextSub.allocate();
329+
assert handle >= 0;
330+
assert isSubpage(handle);
331+
nextSub.chunk.initBufWithSubpage(buf, null, handle, reqCapacity, cache);
332+
return true;
333+
}
334+
handle = allocateSubpage(sizeIdx, head);
335+
if (handle < 0) {
336+
return false;
337+
}
338+
assert isSubpage(handle);
339+
} finally {
340+
head.unlock();
321341
}
322-
assert isSubpage(handle);
323342
} else {
324343
// normal
325344
// runSize must be multiple of pageSize
@@ -432,38 +451,31 @@ private long splitLargeRun(long handle, int needPages) {
432451

433452
/**
434453
* Create / initialize a new PoolSubpage of normCapacity. Any PoolSubpage created / initialized here is added to
435-
* subpage pool in the PoolArena that owns this PoolChunk
454+
* subpage pool in the PoolArena that owns this PoolChunk.
436455
*
437456
* @param sizeIdx sizeIdx of normalized size
457+
* @param head head of subpages
438458
*
439459
* @return index in memoryMap
440460
*/
441-
private long allocateSubpage(int sizeIdx) {
442-
// Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it.
443-
// This is need as we may add it back and so alter the linked-list structure.
444-
PoolSubpage<T> head = arena.findSubpagePoolHead(sizeIdx);
445-
head.lock();
446-
try {
447-
//allocate a new run
448-
int runSize = calculateRunSize(sizeIdx);
449-
//runSize must be multiples of pageSize
450-
long runHandle = allocateRun(runSize);
451-
if (runHandle < 0) {
452-
return -1;
453-
}
461+
private long allocateSubpage(int sizeIdx, PoolSubpage<T> head) {
462+
//allocate a new run
463+
int runSize = calculateRunSize(sizeIdx);
464+
//runSize must be multiples of pageSize
465+
long runHandle = allocateRun(runSize);
466+
if (runHandle < 0) {
467+
return -1;
468+
}
454469

455-
int runOffset = runOffset(runHandle);
456-
assert subpages[runOffset] == null;
457-
int elemSize = arena.sizeIdx2size(sizeIdx);
470+
int runOffset = runOffset(runHandle);
471+
assert subpages[runOffset] == null;
472+
int elemSize = arena.sizeIdx2size(sizeIdx);
458473

459-
PoolSubpage<T> subpage = new PoolSubpage<T>(head, this, pageShifts, runOffset,
460-
runSize(pageShifts, runHandle), elemSize);
474+
PoolSubpage<T> subpage = new PoolSubpage<T>(head, this, pageShifts, runOffset,
475+
runSize(pageShifts, runHandle), elemSize);
461476

462-
subpages[runOffset] = subpage;
463-
return subpage.allocate();
464-
} finally {
465-
head.unlock();
466-
}
477+
subpages[runOffset] = subpage;
478+
return subpage.allocate();
467479
}
468480

469481
/**

0 commit comments

Comments
 (0)