Fix (some) failing tests
Also introduce test sampling, so when the BufferTest is running from an IDE, only 3% of the tests will actually run. The Maven build runs all tests.
This commit is contained in:
parent
513cef1c1e
commit
ab45a7b053
3
pom.xml
3
pom.xml
@ -173,6 +173,9 @@
|
|||||||
<argLine>${argLine.common} ${argLine.printGC} --add-modules jdk.incubator.foreign</argLine>
|
<argLine>${argLine.common} ${argLine.printGC} --add-modules jdk.incubator.foreign</argLine>
|
||||||
<!-- Ensure the whole stacktrace is preserved when an exception is thrown. See https://issues.apache.org/jira/browse/SUREFIRE-1457 -->
|
<!-- Ensure the whole stacktrace is preserved when an exception is thrown. See https://issues.apache.org/jira/browse/SUREFIRE-1457 -->
|
||||||
<trimStackTrace>false</trimStackTrace>
|
<trimStackTrace>false</trimStackTrace>
|
||||||
|
<systemProperties>
|
||||||
|
<sample>nosample</sample>
|
||||||
|
</systemProperties>
|
||||||
</configuration>
|
</configuration>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Declare the surefire dynamic dependencies explicitly, to speed up the docker build. -->
|
<!-- Declare the surefire dynamic dependencies explicitly, to speed up the docker build. -->
|
||||||
|
@ -60,12 +60,19 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
||||||
CLOSED_SEGMENT = MemorySegment.allocateNative(1, scope);
|
// We are not allowed to allocate a zero-sized native buffer, but we *can* take a zero-sized slice from it.
|
||||||
|
// We need the CLOSED_SEGMENT to have a size of zero, because we'll use its size for bounds checks after
|
||||||
|
// the buffer is closed.
|
||||||
|
MemorySegment segment = MemorySegment.allocateNative(1, scope);
|
||||||
|
CLOSED_SEGMENT = segment.asSlice(0, 0);
|
||||||
}
|
}
|
||||||
SEGMENT_CLOSE = new Drop<MemSegBuffer>() {
|
SEGMENT_CLOSE = new Drop<MemSegBuffer>() {
|
||||||
@Override
|
@Override
|
||||||
public void drop(MemSegBuffer buf) {
|
public void drop(MemSegBuffer buf) {
|
||||||
buf.base.scope().close();
|
ResourceScope scope = buf.base.scope();
|
||||||
|
if (!scope.isImplicit()) {
|
||||||
|
scope.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,6 +22,8 @@ import java.lang.ref.Cleaner;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
|
|
||||||
|
import static jdk.incubator.foreign.ResourceScope.newSharedScope;
|
||||||
|
|
||||||
public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
||||||
public static final LongAdder MEM_USAGE_NATIVE = new LongAdder();
|
public static final LongAdder MEM_USAGE_NATIVE = new LongAdder();
|
||||||
private static final ConcurrentHashMap<Long, Runnable> CLEANUP_ACTIONS = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Long, Runnable> CLEANUP_ACTIONS = new ConcurrentHashMap<>();
|
||||||
@ -37,7 +39,7 @@ public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MemorySegment createSegment(long size, Cleaner cleaner) {
|
protected MemorySegment createSegment(long size, Cleaner cleaner) {
|
||||||
final ResourceScope scope = ResourceScope.newSharedScope(cleaner);
|
final ResourceScope scope = cleaner == null ? newSharedScope() : newSharedScope(cleaner);
|
||||||
scope.addOnClose(getCleanupAction(size));
|
scope.addOnClose(getCleanupAction(size));
|
||||||
var segment = MemorySegment.allocateNative(size, scope);
|
var segment = MemorySegment.allocateNative(size, scope);
|
||||||
MEM_USAGE_NATIVE.add(size);
|
MEM_USAGE_NATIVE.add(size);
|
||||||
|
@ -31,10 +31,14 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.ReadOnlyBufferException;
|
import java.nio.ReadOnlyBufferException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.time.temporal.TemporalUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.SplittableRandom;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@ -43,6 +47,7 @@ import java.util.concurrent.SynchronousQueue;
|
|||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.Stream.Builder;
|
import java.util.stream.Stream.Builder;
|
||||||
|
|
||||||
@ -64,7 +69,7 @@ public class BufferTest {
|
|||||||
private static ExecutorService executor;
|
private static ExecutorService executor;
|
||||||
|
|
||||||
private static final Memoize<Fixture[]> ALL_COMBINATIONS = new Memoize<>(
|
private static final Memoize<Fixture[]> ALL_COMBINATIONS = new Memoize<>(
|
||||||
() -> fixtureCombinations().toArray(Fixture[]::new));
|
() -> fixtureCombinations().filter(sample()).toArray(Fixture[]::new));
|
||||||
private static final Memoize<Fixture[]> NON_COMPOSITE = new Memoize<>(
|
private static final Memoize<Fixture[]> NON_COMPOSITE = new Memoize<>(
|
||||||
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(f -> !f.isComposite()).toArray(Fixture[]::new));
|
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(f -> !f.isComposite()).toArray(Fixture[]::new));
|
||||||
private static final Memoize<Fixture[]> HEAP_ALLOCS = new Memoize<>(
|
private static final Memoize<Fixture[]> HEAP_ALLOCS = new Memoize<>(
|
||||||
@ -73,6 +78,19 @@ public class BufferTest {
|
|||||||
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(f -> f.isDirect()).toArray(Fixture[]::new));
|
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(f -> f.isDirect()).toArray(Fixture[]::new));
|
||||||
private static final Memoize<Fixture[]> POOLED_ALLOCS = new Memoize<>(
|
private static final Memoize<Fixture[]> POOLED_ALLOCS = new Memoize<>(
|
||||||
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(f -> f.isPooled()).toArray(Fixture[]::new));
|
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(f -> f.isPooled()).toArray(Fixture[]::new));
|
||||||
|
private static final Memoize<Fixture[]> POOLED_DIRECT_ALLOCS = new Memoize<>(
|
||||||
|
() -> Arrays.stream(ALL_COMBINATIONS.get()).filter(
|
||||||
|
f -> f.isPooled() && f.isDirect()).toArray(Fixture[]::new));
|
||||||
|
|
||||||
|
private static Predicate<Fixture> sample() {
|
||||||
|
String sampleSetting = System.getProperty("sample");
|
||||||
|
if ("nosample".equalsIgnoreCase(sampleSetting)) {
|
||||||
|
return fixture -> true;
|
||||||
|
}
|
||||||
|
Instant today = Instant.now().truncatedTo(ChronoUnit.DAYS);
|
||||||
|
SplittableRandom rng = new SplittableRandom(today.hashCode());
|
||||||
|
return fixture -> rng.nextInt(0, 100) <= 2; // Filter out 97% of tests.
|
||||||
|
}
|
||||||
|
|
||||||
static Fixture[] allocators() {
|
static Fixture[] allocators() {
|
||||||
return ALL_COMBINATIONS.get();
|
return ALL_COMBINATIONS.get();
|
||||||
@ -94,6 +112,10 @@ public class BufferTest {
|
|||||||
return POOLED_ALLOCS.get();
|
return POOLED_ALLOCS.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Fixture[] pooledDirectAllocators() {
|
||||||
|
return POOLED_DIRECT_ALLOCS.get();
|
||||||
|
}
|
||||||
|
|
||||||
static List<Fixture> initialAllocators() {
|
static List<Fixture> initialAllocators() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new Fixture("heap", BufferAllocator::heap, HEAP),
|
new Fixture("heap", BufferAllocator::heap, HEAP),
|
||||||
@ -962,7 +984,7 @@ public class BufferTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled
|
@Disabled // TODO
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("allocators")
|
@MethodSource("allocators")
|
||||||
public void sliceMustBecomeOwnedOnSourceBufferClose(Fixture fixture) {
|
public void sliceMustBecomeOwnedOnSourceBufferClose(Fixture fixture) {
|
||||||
@ -1650,42 +1672,42 @@ public class BufferTest {
|
|||||||
@Nested
|
@Nested
|
||||||
@Isolated
|
@Isolated
|
||||||
class CleanerTests {
|
class CleanerTests {
|
||||||
@Disabled("Precise native memory accounting does not work since recent panama-foreign changes.")
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("io.netty.buffer.api.BufTest#directAllocators")
|
@MethodSource("io.netty.buffer.api.BufferTest#directAllocators")
|
||||||
public void bufferMustBeClosedByCleaner(Fixture fixture) throws InterruptedException {
|
public void bufferMustBeClosedByCleaner(Fixture fixture) throws InterruptedException {
|
||||||
|
var initial = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum();
|
||||||
var allocator = fixture.createAllocator();
|
var allocator = fixture.createAllocator();
|
||||||
allocator.close();
|
allocator.close();
|
||||||
int iterations = 100;
|
int iterations = 50;
|
||||||
int allocationSize = 1024;
|
int allocationSize = 1024;
|
||||||
for (int i = 0; i < iterations; i++) {
|
for (int i = 0; i < iterations; i++) {
|
||||||
allocateAndForget(allocator, allocationSize);
|
allocateAndForget(allocator, allocationSize);
|
||||||
System.gc();
|
System.gc();
|
||||||
System.runFinalization();
|
System.runFinalization();
|
||||||
}
|
}
|
||||||
var sum = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum();
|
var sum = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum() - initial;
|
||||||
var totalAllocated = (long) allocationSize * iterations;
|
var totalAllocated = (long) allocationSize * iterations;
|
||||||
assertThat(sum).isLessThan(totalAllocated);
|
assertThat(sum).isLessThan(totalAllocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void allocateAndForget(BufferAllocator allocator, int size) {
|
private static void allocateAndForget(BufferAllocator allocator, int size) {
|
||||||
allocator.allocate(size);
|
allocator.allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("Precise native memory accounting does not work since recent panama-foreign changes.")
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("io.netty.buffer.api.BufTest#directPooledAllocators")
|
@MethodSource("io.netty.buffer.api.BufferTest#pooledDirectAllocators")
|
||||||
public void buffersMustBeReusedByPoolingAllocatorEvenWhenDroppedByCleanerInsteadOfExplicitly(Fixture fixture)
|
public void buffersMustBeReusedByPoolingAllocatorEvenWhenDroppedByCleanerInsteadOfExplicitly(Fixture fixture)
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
|
var initial = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum();
|
||||||
try (var allocator = fixture.createAllocator()) {
|
try (var allocator = fixture.createAllocator()) {
|
||||||
int iterations = 100;
|
int iterations = 50;
|
||||||
int allocationSize = 1024;
|
int allocationSize = 1024;
|
||||||
for (int i = 0; i < iterations; i++) {
|
for (int i = 0; i < iterations; i++) {
|
||||||
allocateAndForget(allocator, allocationSize);
|
allocateAndForget(allocator, allocationSize);
|
||||||
System.gc();
|
System.gc();
|
||||||
System.runFinalization();
|
System.runFinalization();
|
||||||
}
|
}
|
||||||
var sum = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum();
|
var sum = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum() - initial;
|
||||||
var totalAllocated = (long) allocationSize * iterations;
|
var totalAllocated = (long) allocationSize * iterations;
|
||||||
assertThat(sum).isLessThan(totalAllocated);
|
assertThat(sum).isLessThan(totalAllocated);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user