From d4149e073d12b86c915bd9708385973bb8e7ba25 Mon Sep 17 00:00:00 2001 From: Matteo Di Giovinazzo Date: Sat, 1 Aug 2020 10:53:00 +0200 Subject: [PATCH] Rollback robustness driven changes --- .../java/org/bytedeco/javacpp/Pointer.java | 50 ++++--------- .../org/bytedeco/javacpp/IndexerTest.java | 4 +- .../org/bytedeco/javacpp/PointerTest.java | 72 +++++++++---------- 3 files changed, 51 insertions(+), 75 deletions(-) diff --git a/src/main/java/org/bytedeco/javacpp/Pointer.java b/src/main/java/org/bytedeco/javacpp/Pointer.java index fea5107e4..7b7961688 100644 --- a/src/main/java/org/bytedeco/javacpp/Pointer.java +++ b/src/main/java/org/bytedeco/javacpp/Pointer.java @@ -285,36 +285,12 @@ static class DeallocatorReference extends PhantomReference implements D volatile DeallocatorReference prev = null, next = null; Deallocator deallocator; - private static long totalBytes = 0; - private static long totalCount = 0; + static volatile long totalBytes = 0; + static AtomicLong totalCount = new AtomicLong(); long bytes; AtomicInteger count; - public static long getTotalBytes() { - synchronized (DeallocatorReference.class) { - return DeallocatorReference.totalBytes; - } - } - - static void incrementTotalBytes(long increment) { - synchronized (DeallocatorReference.class) { - DeallocatorReference.totalBytes += increment; - } - } - - static void decrementTotalBytes(long decrement) { - synchronized (DeallocatorReference.class) { - DeallocatorReference.totalBytes -= decrement; - } - } - - public static long getTotalCount() { - synchronized (DeallocatorReference.class) { - return DeallocatorReference.totalCount; - } - } - final void add() { synchronized (DeallocatorReference.class) { if (head == null) { @@ -323,8 +299,8 @@ final void add() { next = head; next.prev = head = this; } - incrementTotalBytes(bytes); - totalCount++; + totalBytes += bytes; + totalCount.incrementAndGet(); } } @@ -342,8 +318,8 @@ final void remove() { next.prev = prev; } prev = next = this; - decrementTotalBytes(bytes); - totalCount--; + totalBytes -= bytes; + totalCount.decrementAndGet(); } } @@ -555,14 +531,14 @@ public static long maxBytes() { return maxBytes; } - /** Returns {@link DeallocatorReference#getTotalBytes()}, current amount of memory tracked by deallocators. */ + /** Returns {@link DeallocatorReference#totalBytes}, current amount of memory tracked by deallocators. */ public static long totalBytes() { - return DeallocatorReference.getTotalBytes(); + return DeallocatorReference.totalBytes; } - /** Returns {@link DeallocatorReference#getTotalCount()}, current number of pointers tracked by deallocators. */ + /** Returns {@link DeallocatorReference#totalCount}, current number of pointers tracked by deallocators. */ public static long totalCount() { - return DeallocatorReference.getTotalCount(); + return DeallocatorReference.totalCount.get(); } /** Returns {@link #maxPhysicalBytes}, the maximum amount of physical memory that should be used. */ @@ -690,7 +666,7 @@ protected

P deallocator(Deallocator deallocator) { long lastPhysicalBytes = maxPhysicalBytes > 0 ? physicalBytes() : 0; synchronized (DeallocatorThread.class) { try { - while (count++ < maxRetries && ((maxBytes > 0 && DeallocatorReference.getTotalBytes() + r.bytes > maxBytes) + while (count++ < maxRetries && ((maxBytes > 0 && DeallocatorReference.totalBytes + r.bytes > maxBytes) || (maxPhysicalBytes > 0 && lastPhysicalBytes > maxPhysicalBytes))) { if (logger.isDebugEnabled()) { logger.debug("Calling System.gc() and Pointer.trimMemory() in " + this); @@ -710,10 +686,10 @@ protected

P deallocator(Deallocator deallocator) { logger.debug(e.getMessage()); } } - if (maxBytes > 0 && DeallocatorReference.getTotalBytes() + r.bytes > maxBytes) { + if (maxBytes > 0 && DeallocatorReference.totalBytes + r.bytes > maxBytes) { deallocate(); throw new OutOfMemoryError("Failed to allocate memory within limits: totalBytes (" - + formatBytes(DeallocatorReference.getTotalBytes()) + " + " + formatBytes(r.bytes) + ") > maxBytes (" + formatBytes(maxBytes) + ")"); + + formatBytes(DeallocatorReference.totalBytes) + " + " + formatBytes(r.bytes) + ") > maxBytes (" + formatBytes(maxBytes) + ")"); } else if (maxPhysicalBytes > 0 && lastPhysicalBytes > maxPhysicalBytes) { deallocate(); throw new OutOfMemoryError("Physical memory usage is too high: physicalBytes (" diff --git a/src/test/java/org/bytedeco/javacpp/IndexerTest.java b/src/test/java/org/bytedeco/javacpp/IndexerTest.java index 65aed0993..9624d2397 100644 --- a/src/test/java/org/bytedeco/javacpp/IndexerTest.java +++ b/src/test/java/org/bytedeco/javacpp/IndexerTest.java @@ -75,11 +75,11 @@ public class IndexerTest { Loader.load(c); // work around OutOfMemoryError when testing long indexing - Pointer.DeallocatorReference.decrementTotalBytes(1L << 48); + Pointer.DeallocatorReference.totalBytes -= 1L << 48; } @AfterClass public static void tearDownClass() throws Exception { - Pointer.DeallocatorReference.incrementTotalBytes(1L << 48); + Pointer.DeallocatorReference.totalBytes += 1L << 48; } static class TestIndexer extends Indexer { diff --git a/src/test/java/org/bytedeco/javacpp/PointerTest.java b/src/test/java/org/bytedeco/javacpp/PointerTest.java index 64b8fbda5..db1e9ee41 100644 --- a/src/test/java/org/bytedeco/javacpp/PointerTest.java +++ b/src/test/java/org/bytedeco/javacpp/PointerTest.java @@ -233,7 +233,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new BytePointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * byteSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * byteSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -249,9 +249,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new BytePointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * byteSize); - assertTrue(Pointer.totalBytes() >= chunkSize * byteSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * byteSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * byteSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * byteSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * byteSize); } @Test public void testShortPointer() { @@ -316,7 +316,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new ShortPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * shortSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * shortSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -332,9 +332,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new ShortPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * shortSize); - assertTrue(Pointer.totalBytes() >= chunkSize * shortSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * shortSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * shortSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * shortSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * shortSize); } @Test public void testIntPointer() { @@ -399,7 +399,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new IntPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * intSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * intSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -415,9 +415,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new IntPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * intSize); - assertTrue(Pointer.totalBytes() >= chunkSize * intSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * intSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * intSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * intSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * intSize); } @Test public void testLongPointer() { @@ -482,7 +482,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new LongPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * longSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * longSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -498,9 +498,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new LongPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * longSize); - assertTrue(Pointer.totalBytes() >= chunkSize * longSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * longSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * longSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * longSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * longSize); } @Test public void testFloatPointer() { @@ -565,7 +565,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new FloatPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * floatSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * floatSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -581,9 +581,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new FloatPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * floatSize); - assertTrue(Pointer.totalBytes() >= chunkSize * floatSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * floatSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * floatSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * floatSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * floatSize); } @Test public void testDoublePointer() { @@ -648,7 +648,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new DoublePointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * doubleSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * doubleSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -664,9 +664,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new DoublePointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * doubleSize); - assertTrue(Pointer.totalBytes() >= chunkSize * doubleSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * doubleSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * doubleSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * doubleSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * doubleSize); } @Test public void testCharPointer() { @@ -731,7 +731,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new CharPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * charSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * charSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -747,9 +747,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new CharPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * charSize); - assertTrue(Pointer.totalBytes() >= chunkSize * charSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * charSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * charSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * charSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * charSize); } @Test public void testBooleanPointer() { @@ -813,7 +813,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new BooleanPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * booleanSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * booleanSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -829,9 +829,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new BooleanPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * booleanSize); - assertTrue(Pointer.totalBytes() >= chunkSize * booleanSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * booleanSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * booleanSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * booleanSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * booleanSize); } @Test public void testPointerPointer() { @@ -904,7 +904,7 @@ static class TestFunction extends FunctionPointer { for (int j = 0; j < chunks - 1; j++) { pointers[j] = new PointerPointer(chunkSize); } - assertTrue(Pointer.totalBytes() >= (chunks - 1) * chunkSize * pointerSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= (chunks - 1) * chunkSize * pointerSize); try { fieldReference = pointers; System.out.println("Note: OutOfMemoryError should get thrown here and printed below."); @@ -920,9 +920,9 @@ static class TestFunction extends FunctionPointer { // make sure garbage collection runs fieldReference = null; pointers[0] = new PointerPointer(chunkSize); - assertTrue(Pointer.totalBytes() < (chunks - 1) * chunkSize * pointerSize); - assertTrue(Pointer.totalBytes() >= chunkSize * pointerSize); - System.out.println(Pointer.totalBytes() + " " + chunkSize * pointerSize); + assertTrue(Pointer.DeallocatorReference.totalBytes < (chunks - 1) * chunkSize * pointerSize); + assertTrue(Pointer.DeallocatorReference.totalBytes >= chunkSize * pointerSize); + System.out.println(Pointer.DeallocatorReference.totalBytes + " " + chunkSize * pointerSize); } @Test public void testDeallocator() throws InterruptedException {