82 List<Thread> threads = IntStream.range(0, 100)
83 .mapToObj(_ -> Thread.startVirtualThread(() -> { }))
84 .toList();
85 for (Thread t : threads) {
86 t.join();
87 }
88 } finally {
89 recording.stop();
90 }
91
92 Map<String, Integer> events = sumEvents(recording);
93 System.err.println(events);
94
95 int startCount = events.getOrDefault("jdk.VirtualThreadStart", 0);
96 int endCount = events.getOrDefault("jdk.VirtualThreadEnd", 0);
97 assertEquals(100, startCount);
98 assertEquals(100, endCount);
99 }
100 }
101
102 /**
103 * Test jdk.VirtualThreadPinned event when parking while pinned.
104 */
105 @ParameterizedTest
106 @ValueSource(booleans = { true, false })
107 void testParkWhenPinned(boolean timed) throws Exception {
108 try (Recording recording = new Recording()) {
109 recording.enable("jdk.VirtualThreadPinned");
110 recording.start();
111
112 var started = new AtomicBoolean();
113 var done = new AtomicBoolean();
114 var vthread = Thread.startVirtualThread(() -> {
115 VThreadPinner.runPinned(() -> {
116 started.set(true);
117 while (!done.get()) {
118 if (timed) {
119 LockSupport.parkNanos(Long.MAX_VALUE);
120 } else {
121 LockSupport.park();
437 recordingFile = Path.of("recording-" + recording.getId() + "-pid" + h.pid() + ".jfr");
438 recording.dump(recordingFile);
439 }
440 return recordingFile;
441 }
442
443 /**
444 * Assert that a recording contains a jdk.VirtualThreadPinned event on the given thread.
445 */
446 private void assertContainsPinnedEvent(Recording recording, Thread thread) throws IOException {
447 List<RecordedEvent> pinnedEvents = find(recording, "jdk.VirtualThreadPinned");
448 assertTrue(pinnedEvents.size() > 0, "No jdk.VirtualThreadPinned events in recording");
449 System.err.println(pinnedEvents);
450
451 long tid = thread.threadId();
452 assertTrue(pinnedEvents.stream()
453 .anyMatch(e -> e.getThread().getJavaThreadId() == tid),
454 "jdk.VirtualThreadPinned for javaThreadId = " + tid + " not found");
455 }
456
457 /**
458 * Waits for the given boolean to be set to true.
459 */
460 private void awaitTrue(AtomicBoolean b) throws InterruptedException {
461 while (!b.get()) {
462 Thread.sleep(10);
463 }
464 }
465
466 /**
467 * Waits for the given thread to reach a given state.
468 */
469 private static void await(Thread thread, Thread.State expectedState) throws InterruptedException {
470 Thread.State state = thread.getState();
471 while (state != expectedState) {
472 Thread.sleep(10);
473 state = thread.getState();
474 }
475 }
476 }
|
82 List<Thread> threads = IntStream.range(0, 100)
83 .mapToObj(_ -> Thread.startVirtualThread(() -> { }))
84 .toList();
85 for (Thread t : threads) {
86 t.join();
87 }
88 } finally {
89 recording.stop();
90 }
91
92 Map<String, Integer> events = sumEvents(recording);
93 System.err.println(events);
94
95 int startCount = events.getOrDefault("jdk.VirtualThreadStart", 0);
96 int endCount = events.getOrDefault("jdk.VirtualThreadEnd", 0);
97 assertEquals(100, startCount);
98 assertEquals(100, endCount);
99 }
100 }
101
102 /**
103 * Test jdk.VirtualThreadPark.
104 */
105 @ParameterizedTest
106 @ValueSource(longs = { 0, 30_000_000_000L, Long.MAX_VALUE })
107 void testPark(long timeout) throws Exception {
108 try (Recording recording = new Recording()) {
109 recording.enable("jdk.VirtualThreadPark");
110
111 recording.start();
112
113 var started = new AtomicBoolean();
114 var done = new AtomicBoolean();
115 var vthread = Thread.startVirtualThread(() -> {
116 started.set(true);
117 while (!done.get()) {
118 if (timeout > 0) {
119 LockSupport.parkNanos(timeout);
120 } else {
121 LockSupport.park();
122 }
123 }
124 });
125
126 try {
127 // wait for thread to start and park
128 awaitTrue(started);
129 await(vthread, timeout > 0 ? Thread.State.TIMED_WAITING : Thread.State.WAITING);
130 } finally {
131 done.set(true);
132 LockSupport.unpark(vthread);
133 vthread.join();
134 recording.stop();
135 }
136
137 assertContainsParkEvent(recording, vthread, timeout);
138 }
139
140 }
141
142 /**
143 * Test jdk.VirtualThreadPinned event when parking while pinned.
144 */
145 @ParameterizedTest
146 @ValueSource(booleans = { true, false })
147 void testParkWhenPinned(boolean timed) throws Exception {
148 try (Recording recording = new Recording()) {
149 recording.enable("jdk.VirtualThreadPinned");
150 recording.start();
151
152 var started = new AtomicBoolean();
153 var done = new AtomicBoolean();
154 var vthread = Thread.startVirtualThread(() -> {
155 VThreadPinner.runPinned(() -> {
156 started.set(true);
157 while (!done.get()) {
158 if (timed) {
159 LockSupport.parkNanos(Long.MAX_VALUE);
160 } else {
161 LockSupport.park();
477 recordingFile = Path.of("recording-" + recording.getId() + "-pid" + h.pid() + ".jfr");
478 recording.dump(recordingFile);
479 }
480 return recordingFile;
481 }
482
483 /**
484 * Assert that a recording contains a jdk.VirtualThreadPinned event on the given thread.
485 */
486 private void assertContainsPinnedEvent(Recording recording, Thread thread) throws IOException {
487 List<RecordedEvent> pinnedEvents = find(recording, "jdk.VirtualThreadPinned");
488 assertTrue(pinnedEvents.size() > 0, "No jdk.VirtualThreadPinned events in recording");
489 System.err.println(pinnedEvents);
490
491 long tid = thread.threadId();
492 assertTrue(pinnedEvents.stream()
493 .anyMatch(e -> e.getThread().getJavaThreadId() == tid),
494 "jdk.VirtualThreadPinned for javaThreadId = " + tid + " not found");
495 }
496
497 /**
498 * Assert that a recording contains a jdk.VirtualThreadPark event on the given thread.
499 */
500 private void assertContainsParkEvent(Recording recording,
501 Thread thread,
502 long testTimeout) throws IOException {
503 List<RecordedEvent> allParkEvents = find(recording, "jdk.VirtualThreadPark");
504 assertTrue(allParkEvents.size() > 0, "No jdk.VirtualThreadPark events in recording");
505 System.err.println(allParkEvents);
506
507 // park events for the given thread
508 long tid = thread.threadId();
509 List<RecordedEvent> parkEvents = allParkEvents.stream()
510 .filter(e -> e.getThread().getJavaThreadId() == tid)
511 .toList();
512
513 long expectedTimeout = (testTimeout != 0) ? testTimeout : Long.MIN_VALUE;
514 boolean found = parkEvents.stream()
515 .map(e -> e.getLong("timeout"))
516 .allMatch(t -> t == expectedTimeout);
517 assertTrue(found, "jdk.VirtualThreadPark for javaThreadId = " + tid
518 + ", timeout = " + expectedTimeout + " not found");
519 }
520
521 /**
522 * Waits for the given boolean to be set to true.
523 */
524 private void awaitTrue(AtomicBoolean b) throws InterruptedException {
525 while (!b.get()) {
526 Thread.sleep(10);
527 }
528 }
529
530 /**
531 * Waits for the given thread to reach a given state.
532 */
533 private static void await(Thread thread, Thread.State expectedState) throws InterruptedException {
534 Thread.State state = thread.getState();
535 while (state != expectedState) {
536 Thread.sleep(10);
537 state = thread.getState();
538 }
539 }
540 }
|