Fix memory release failure when "maxNumElems == 1" of PoolSubpage (#10988)
Motivation: when customer need large of 'byteBuf.capacity' in [7168, 8192], the size of 'chunk.subpages' may be inflated when large of byteBuf be released, not consistent with other 'byteBuf.capacity' Modification: when maxNumElems == 1 need consider remove from pool Result: Fixes #10896. Co-authored-by: zxingy <zxingy@servyou.com.cn>
This commit is contained in:
parent
5460ae7d54
commit
d0bcf44445
@ -115,8 +115,14 @@ final class PoolSubpage<T> implements PoolSubpageMetric {
|
|||||||
|
|
||||||
if (numAvail ++ == 0) {
|
if (numAvail ++ == 0) {
|
||||||
addToPool(head);
|
addToPool(head);
|
||||||
|
/* When maxNumElems == 1, the maximum numAvail is also 1.
|
||||||
|
* Each of these PoolSubpages will go in here when they do free operation.
|
||||||
|
* If they return true directly from here, then the rest of the code will be unreachable
|
||||||
|
* and they will not actually be recycled. So return true only on maxNumElems > 1. */
|
||||||
|
if (maxNumElems > 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (numAvail != maxNumElems) {
|
if (numAvail != maxNumElems) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -632,8 +632,8 @@ public class PooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest<Poo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static PooledByteBuf<ByteBuffer> unwrapIfNeeded(ByteBuf buf) {
|
private static <T> PooledByteBuf<T> unwrapIfNeeded(ByteBuf buf) {
|
||||||
return (PooledByteBuf<ByteBuffer>) (buf instanceof PooledByteBuf ? buf : buf.unwrap());
|
return (PooledByteBuf<T>) (buf instanceof PooledByteBuf ? buf : buf.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -661,4 +661,27 @@ public class PooledByteBufAllocatorTest extends AbstractByteBufAllocatorTest<Poo
|
|||||||
assertEquals(3, allocator.metric().directArenas().get(0).numNormalAllocations());
|
assertEquals(3, allocator.metric().directArenas().get(0).numNormalAllocations());
|
||||||
buffer.release();
|
buffer.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormalPoolSubpageRelease() {
|
||||||
|
// 16 < elemSize <= 7168 or 8192 < elemSize <= 28672, 1 < subpage.maxNumElems <= 256
|
||||||
|
// 7168 <= elemSize <= 8192, subpage.maxNumElems == 1
|
||||||
|
int elemSize = 8192;
|
||||||
|
int length = 1024;
|
||||||
|
ByteBuf[] byteBufs = new ByteBuf[length];
|
||||||
|
final PooledByteBufAllocator allocator = new PooledByteBufAllocator(false, 32, 32, 8192, 11, 256, 64, false, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
byteBufs[i] = allocator.heapBuffer(elemSize, elemSize);
|
||||||
|
}
|
||||||
|
PoolChunk<Object> chunk = unwrapIfNeeded(byteBufs[0]).chunk;
|
||||||
|
|
||||||
|
int beforeFreeBytes = chunk.freeBytes();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
byteBufs[i].release();
|
||||||
|
}
|
||||||
|
int afterFreeBytes = chunk.freeBytes();
|
||||||
|
|
||||||
|
assertTrue(beforeFreeBytes < afterFreeBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user