From 3d3271e1ea3dba44905e16e8f26b870552b701db Mon Sep 17 00:00:00 2001 From: mperor Date: Sat, 22 Feb 2025 18:30:24 +0100 Subject: [PATCH] Adjust tests for Java 21 & add helper for performance testing --- .../java/pl/mperor/lab/common/TestUtils.java | 7 +++ .../test/java/pl/mperor/lab/java/Java21.java | 50 ++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/Common/src/main/java/pl/mperor/lab/common/TestUtils.java b/Common/src/main/java/pl/mperor/lab/common/TestUtils.java index 83f071a..9f54a0c 100644 --- a/Common/src/main/java/pl/mperor/lab/common/TestUtils.java +++ b/Common/src/main/java/pl/mperor/lab/common/TestUtils.java @@ -60,4 +60,11 @@ private E getNext(int index) { } } + public static long measureExecutionTimeMillis(Runnable task) { + long startTime = System.currentTimeMillis(); + task.run(); + long endTime = System.currentTimeMillis(); + return endTime - startTime; + } + } diff --git a/JavaReleases/src/test/java/pl/mperor/lab/java/Java21.java b/JavaReleases/src/test/java/pl/mperor/lab/java/Java21.java index 976225a..0a15772 100644 --- a/JavaReleases/src/test/java/pl/mperor/lab/java/Java21.java +++ b/JavaReleases/src/test/java/pl/mperor/lab/java/Java21.java @@ -4,10 +4,11 @@ import org.junit.jupiter.api.Test; import pl.mperor.lab.common.TestUtils; -import java.util.Collections; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.SequencedCollection; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.IntStream; /// Java 21™ (September 2023) /// [JDK 21](https://openjdk.org/projects/jdk/21) @@ -35,6 +36,7 @@ public class Java21 { @Test public void testVirtualThreads() throws InterruptedException { TestUtils.ReadableOut out = TestUtils.setTempSystemOut(); + // same as Thread.ofVirtual().start(() -> ...) Thread virtualThread = Thread.startVirtualThread(() -> System.out.print("Hello from Virtual Thread!") ); @@ -46,13 +48,45 @@ public void testVirtualThreads() throws InterruptedException { Assertions.assertEquals("Hello from Virtual Thread!", out.all()); } + + @Test + public void testVirtualVsPlatformThreads() { + final int threadPool = 100; + + long virtualThreadsTime = TestUtils.measureExecutionTimeMillis(() -> { + try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { + execute(threadPool, executor); + } + } + ); + + long platformThreadsTime = TestUtils.measureExecutionTimeMillis(() -> { + try (var executor = Executors.newFixedThreadPool(threadPool)) { + execute(threadPool, executor); + } + } + ); + + System.out.println("🌀 virtual threads: %s [ms]".formatted(virtualThreadsTime)); + System.out.println("🖥️ platform threads: %s [ms]".formatted(platformThreadsTime)); + Assertions.assertTrue(platformThreadsTime > virtualThreadsTime); + } + + private static void execute(int threadPool, ExecutorService executor) { + IntStream.rangeClosed(0, threadPool).forEach(i -> executor.submit(() -> { + Thread.sleep(Duration.ofMillis(100)); + return i; + })); + } + @Test public void testSequencedCollections() { List letters = List.of("one", "two", "three"); - Assertions.assertInstanceOf(SequencedCollection.class, letters); Assertions.assertEquals("one", letters.getFirst()); Assertions.assertEquals("three", letters.getLast()); Assertions.assertThrows(NoSuchElementException.class, Collections.emptyList()::getFirst); + Assertions.assertInstanceOf(SequencedCollection.class, letters); + Assertions.assertInstanceOf(SequencedCollection.class, new LinkedHashMap<>().keySet()); } @Test @@ -70,7 +104,8 @@ record LineSegment(Point start, Point end) {} @Test public void testSwitchPatternMatching() { - Assertions.assertEquals("String: Hello", switchOverClasses("Hello")); + Assertions.assertEquals("Short String: abc", switchOverClasses("abc")); + Assertions.assertEquals("Long String: longer than abc", switchOverClasses("longer than abc")); Assertions.assertEquals("int: 1", switchOverClasses(1)); Assertions.assertEquals("long: 13", switchOverClasses(13L)); Assertions.assertEquals("boolean: true", switchOverClasses(true)); @@ -86,7 +121,8 @@ public String toString() { private static String switchOverClasses(Object obj) { return switch (obj) { - case String s -> String.format("String: %s", s); + case String s when s.length() <= 3 -> String.format("Short String: %s", s); + case String s -> String.format("Long String: %s", s); case Integer i -> String.format("int: %d", i); case Long l -> String.format("long: %d", l); case Boolean b -> String.format("boolean: %s", b);