Fix offset calculation in PooledByteBufAllocator when used

Motivation:

When we create new chunk with memory aligned, the offset of direct memory should be
'alignment - address & (alignment - 1)', not just 'address & (alignment - 1)'.

Modification:

Change offset calculating formula to offset = alignment - address & (alignment - 1) in PoolArena.DirectArena#offsetCacheLine and add a unit test to assert that.

Result:

Correctly calculate offset.
This commit is contained in:
Rolandz 2018-11-27 18:47:34 +08:00 committed by Norman Maurer
parent cb1090653f
commit 836c39b82f
2 changed files with 28 additions and 3 deletions

View File

@ -725,11 +725,16 @@ abstract class PoolArena<T> implements PoolArenaMetric {
return true; return true;
} }
private int offsetCacheLine(ByteBuffer memory) { // mark as package-private, only for unit test
int offsetCacheLine(ByteBuffer memory) {
// We can only calculate the offset if Unsafe is present as otherwise directBufferAddress(...) will // We can only calculate the offset if Unsafe is present as otherwise directBufferAddress(...) will
// throw an NPE. // throw an NPE.
return HAS_UNSAFE ? int remainder = HAS_UNSAFE
(int) (PlatformDependent.directBufferAddress(memory) & directMemoryCacheAlignmentMask) : 0; ? (int) (PlatformDependent.directBufferAddress(memory) & directMemoryCacheAlignmentMask)
: 0;
// offset = alignment - address & (alignment - 1)
return directMemoryCacheAlignment - remainder;
} }
@Override @Override

View File

@ -16,6 +16,7 @@
package io.netty.buffer; package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -43,6 +44,25 @@ public class PoolArenaTest {
} }
} }
@Test
public void testDirectArenaOffsetCacheLine() throws Exception {
int capacity = 5;
int alignment = 128;
for (int i = 0; i < 1000; i++) {
ByteBuffer bb = PlatformDependent.useDirectBufferNoCleaner()
? PlatformDependent.allocateDirectNoCleaner(capacity + alignment)
: ByteBuffer.allocateDirect(capacity + alignment);
PoolArena.DirectArena arena = new PoolArena.DirectArena(null, 0, 0, 9, 9, alignment);
int offset = arena.offsetCacheLine(bb);
long address = PlatformDependent.directBufferAddress(bb);
Assert.assertEquals(0, (offset + address) & (alignment - 1));
PlatformDependent.freeDirectBuffer(bb);
}
}
@Test @Test
public final void testAllocationCounter() { public final void testAllocationCounter() {
final PooledByteBufAllocator allocator = new PooledByteBufAllocator( final PooledByteBufAllocator allocator = new PooledByteBufAllocator(