From ec9875d084bba34ccf53b5718b48207bb8245ad0 Mon Sep 17 00:00:00 2001 From: old driver Date: Fri, 18 Aug 2023 16:51:43 +0800 Subject: [PATCH] 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 --- .../main/java/io/netty/buffer/PoolChunk.java | 68 +++++++++++-------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/PoolChunk.java b/buffer/src/main/java/io/netty/buffer/PoolChunk.java index edbe9a12c5a..3a65f383c67 100644 --- a/buffer/src/main/java/io/netty/buffer/PoolChunk.java +++ b/buffer/src/main/java/io/netty/buffer/PoolChunk.java @@ -314,12 +314,31 @@ private int usage(int freeBytes) { boolean allocate(PooledByteBuf buf, int reqCapacity, int sizeIdx, PoolThreadCache cache) { final long handle; if (sizeIdx <= arena.smallMaxSizeIdx) { + final PoolSubpage nextSub; // small - handle = allocateSubpage(sizeIdx); - if (handle < 0) { - return false; + // Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it. + // This is need as we may add it back and so alter the linked-list structure. + PoolSubpage head = arena.findSubpagePoolHead(sizeIdx); + head.lock(); + try { + nextSub = head.next; + if (nextSub != head) { + assert nextSub.doNotDestroy && nextSub.elemSize == arena.sizeIdx2size(sizeIdx) : "doNotDestroy=" + + nextSub.doNotDestroy + ", elemSize=" + nextSub.elemSize + ", sizeIdx=" + sizeIdx; + handle = nextSub.allocate(); + assert handle >= 0; + assert isSubpage(handle); + nextSub.chunk.initBufWithSubpage(buf, null, handle, reqCapacity, cache); + return true; + } + handle = allocateSubpage(sizeIdx, head); + if (handle < 0) { + return false; + } + assert isSubpage(handle); + } finally { + head.unlock(); } - assert isSubpage(handle); } else { // normal // runSize must be multiple of pageSize @@ -432,38 +451,31 @@ private long splitLargeRun(long handle, int needPages) { /** * Create / initialize a new PoolSubpage of normCapacity. Any PoolSubpage created / initialized here is added to - * subpage pool in the PoolArena that owns this PoolChunk + * subpage pool in the PoolArena that owns this PoolChunk. * * @param sizeIdx sizeIdx of normalized size + * @param head head of subpages * * @return index in memoryMap */ - private long allocateSubpage(int sizeIdx) { - // Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it. - // This is need as we may add it back and so alter the linked-list structure. - PoolSubpage head = arena.findSubpagePoolHead(sizeIdx); - head.lock(); - try { - //allocate a new run - int runSize = calculateRunSize(sizeIdx); - //runSize must be multiples of pageSize - long runHandle = allocateRun(runSize); - if (runHandle < 0) { - return -1; - } + private long allocateSubpage(int sizeIdx, PoolSubpage head) { + //allocate a new run + int runSize = calculateRunSize(sizeIdx); + //runSize must be multiples of pageSize + long runHandle = allocateRun(runSize); + if (runHandle < 0) { + return -1; + } - int runOffset = runOffset(runHandle); - assert subpages[runOffset] == null; - int elemSize = arena.sizeIdx2size(sizeIdx); + int runOffset = runOffset(runHandle); + assert subpages[runOffset] == null; + int elemSize = arena.sizeIdx2size(sizeIdx); - PoolSubpage subpage = new PoolSubpage(head, this, pageShifts, runOffset, - runSize(pageShifts, runHandle), elemSize); + PoolSubpage subpage = new PoolSubpage(head, this, pageShifts, runOffset, + runSize(pageShifts, runHandle), elemSize); - subpages[runOffset] = subpage; - return subpage.allocate(); - } finally { - head.unlock(); - } + subpages[runOffset] = subpage; + return subpage.allocate(); } /**