Add a BBuf allocator for direct memory, that is also managed by a Cleaner
Motivation: Client code sometimes struggle with managing their buffer reference counts correctly, so there's a use case for buffers that are deallocated by cleaners. Modification: Add another allocator, directWithCleaner, which registers all the native memory segments with cleaners. Result: It's possible to get unpooled direct buffers, that are automatically deallocated by a cleaner if they are no longer strongly referenced. The same is not necessary for heap buffers, since they can be garbage collected like normal objects.
This commit is contained in:
parent
1aa439991a
commit
1f4e33b42a
@ -74,6 +74,18 @@ public interface Allocator extends AutoCloseable {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Allocator directWithCleaner() {
|
||||||
|
return new Allocator() {
|
||||||
|
@Override
|
||||||
|
public Buf allocate(long size) {
|
||||||
|
checkSize(size);
|
||||||
|
var segment = allocateNative(size);
|
||||||
|
segment.registerCleaner(Statics.CLEANER);
|
||||||
|
return new BBuf(segment, SEGMENT_CLOSE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static Allocator pooledHeap() {
|
static Allocator pooledHeap() {
|
||||||
return new SizeClassedMemoryPool() {
|
return new SizeClassedMemoryPool() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package io.netty.buffer.b2;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class DirectBBufWithCleanerTest extends DirectBBufTest {
|
||||||
|
@Override
|
||||||
|
protected Allocator createAllocator() {
|
||||||
|
return Allocator.directWithCleaner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bufferMustBeClosedByCleaner() throws InterruptedException {
|
||||||
|
var allocator = createAllocator();
|
||||||
|
allocator.close();
|
||||||
|
int iterations = 100;
|
||||||
|
int allocationSize = 1024;
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
allocateAndForget(allocator, allocationSize);
|
||||||
|
System.gc();
|
||||||
|
System.runFinalization();
|
||||||
|
}
|
||||||
|
var sum = Statics.MEM_USAGE_NATIVE.sum();
|
||||||
|
var totalAllocated = (long) allocationSize * iterations;
|
||||||
|
assertThat(sum, lessThan(totalAllocated));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void allocateAndForget(Allocator allocator, long size) {
|
||||||
|
allocator.allocate(size);
|
||||||
|
}
|
||||||
|
}
|
@ -20,28 +20,12 @@ import org.junit.Test;
|
|||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class PooledDirectBBufWithCleanerTest extends DirectBBufTest {
|
public class PooledDirectBBufWithCleanerTest extends DirectBBufWithCleanerTest {
|
||||||
@Override
|
@Override
|
||||||
protected Allocator createAllocator() {
|
protected Allocator createAllocator() {
|
||||||
return Allocator.pooledDirectWithCleaner();
|
return Allocator.pooledDirectWithCleaner();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bufferMustBeClosedByCleaner() throws InterruptedException {
|
|
||||||
var allocator = createAllocator();
|
|
||||||
allocator.close();
|
|
||||||
int iterations = 100;
|
|
||||||
int allocationSize = 1024;
|
|
||||||
for (int i = 0; i < iterations; i++) {
|
|
||||||
allocateAndForget(allocator, allocationSize);
|
|
||||||
System.gc();
|
|
||||||
System.runFinalization();
|
|
||||||
}
|
|
||||||
var sum = Statics.MEM_USAGE_NATIVE.sum();
|
|
||||||
var totalAllocated = (long) allocationSize * iterations;
|
|
||||||
assertThat(sum, lessThan(totalAllocated));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buffersMustBeReusedByPoolingAllocatorEvenWhenDroppedByCleanerInsteadOfExplicitly()
|
public void buffersMustBeReusedByPoolingAllocatorEvenWhenDroppedByCleanerInsteadOfExplicitly()
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
@ -58,8 +42,4 @@ public class PooledDirectBBufWithCleanerTest extends DirectBBufTest {
|
|||||||
assertThat(sum, lessThan(totalAllocated));
|
assertThat(sum, lessThan(totalAllocated));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void allocateAndForget(Allocator allocator, long size) {
|
|
||||||
allocator.allocate(size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user