diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/MemorySafeLinkedBlockingQueueTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/MemorySafeLinkedBlockingQueueTest.java index e678cbd14b..2a2372db05 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/MemorySafeLinkedBlockingQueueTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/MemorySafeLinkedBlockingQueueTest.java @@ -17,13 +17,14 @@ package org.apache.dubbo.common.threadpool; +import net.bytebuddy.agent.ByteBuddyAgent; import org.apache.dubbo.common.concurrent.AbortPolicy; import org.apache.dubbo.common.concurrent.RejectException; - -import net.bytebuddy.agent.ByteBuddyAgent; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.lang.instrument.Instrumentation; +import java.util.concurrent.LinkedBlockingQueue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -55,4 +56,59 @@ class MemorySafeLinkedBlockingQueueTest { assertThrows(RejectException.class, () -> queue.offer(() -> { })); } + + @Test + void testEfficiency() throws InterruptedException { + // if length is vert large(unit test may runs for a long time), so you may need to modify JVM param such as : -Xms=1024m -Xmx=2048m + // if you want to test efficiency of MemorySafeLinkedBlockingQueue, you may modify following param: length and times + int length = 1000, times = 1; + + // LinkedBlockingQueue insert Integer: 500W * 20 times + long spent1 = spend(new LinkedBlockingQueue<>(), length, times); + + // MemorySafeLinkedBlockingQueue insert Integer: 500W * 20 times + long spent2 = spend(newMemorySafeLinkedBlockingQueue(), length, times); + System.gc(); + + System.out.println(String.format("LinkedBlockingQueue spent %s millis, MemorySafeLinkedBlockingQueue spent %s millis", spent1, spent2)); + // efficiency between LinkedBlockingQueue and MemorySafeLinkedBlockingQueue is very nearly the same + Assertions.assertTrue(spent1 - spent2 <= 1); + } + + private static long spend(LinkedBlockingQueue lbq, int length, int times) throws InterruptedException { + // new Queue + if (lbq instanceof MemorySafeLinkedBlockingQueue) { + lbq = newMemorySafeLinkedBlockingQueue(); + } else { + lbq = new LinkedBlockingQueue<>(); + } + + long total = 0L; + for (int i = 0; i < times; i++) { + long start = System.currentTimeMillis(); + for (int j = 0; j < length; j++) { + lbq.offer(j); + } + long end = System.currentTimeMillis(); + long spent = end - start; + total += spent; + } + long result = total / times; + + // gc + System.gc(); + + return result; + } + + private static MemorySafeLinkedBlockingQueue newMemorySafeLinkedBlockingQueue() { + ByteBuddyAgent.install(); + final Instrumentation instrumentation = ByteBuddyAgent.getInstrumentation(); + final long objectSize = instrumentation.getObjectSize((Runnable) () -> { }); + int maxFreeMemory = (int) MemoryLimitCalculator.maxAvailable(); + MemorySafeLinkedBlockingQueue queue = new MemorySafeLinkedBlockingQueue<>(maxFreeMemory); + queue.setMaxFreeMemory((int) (MemoryLimitCalculator.maxAvailable() - objectSize)); + queue.setRejector(new AbortPolicy<>()); + return queue; + } }