<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
Hi Masoud,<br>
<br>
Thanks for testing the latest EA build.<br>
<br>
<div class="moz-cite-prefix">On 2/27/24 3:28 PM, masoud parvari
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CAOgKQu0qFvXOx2Cw5vJJS+V4pPctgEkbqhJerL8rzweo+Y1h=Q@mail.gmail.com">
<div dir="ltr">public class VirtualThreadPerformanceTest {<br>
<div><br>
public static void main(String[] args) throws
InterruptedException {<br>
int size = 1000;<br>
test(false, size);<br>
test(true, size);<br>
}<br>
<br>
private static void test(boolean isVirtual, int size)
throws InterruptedException {<br>
ExecutorService executorService = isVirtual == true ?
Executors.newVirtualThreadPerTaskExecutor()<br>
:
Executors.newThreadPerTaskExecutor(Thread.ofPlatform().factory());<br>
CountDownLatch latch = new CountDownLatch(size);<br>
long start = System.currentTimeMillis();<br>
Object object = new Object();<br>
for (int i = 0; i < size; i++) {<br>
executorService.submit(() -> {<br>
synchronized (object) {<br>
try {<br>
object.wait(100);<br>
} catch (InterruptedException e) {<br>
//do nothing;<br>
}<br>
}<br>
latch.countDown();<br>
});<br>
}<br>
synchronized (object) {<br>
object.notifyAll();<br>
}<br>
latch.await();<br>
long duration = System.currentTimeMillis() - start;<br>
System.out.println((isVirtual? "Virtual" : "Platform")
+ " took " + duration + " milliseconds");<br>
}<br>
}<br>
</div>
<div><br>
</div>
<div>To my surprise, Virtual thread is significantly slower than
platform thread here. 4x-5x. And also virtual thread on new
build is consistently slower than java 21 in this scenario,
around 100-200 milliseconds in above example which is
significant. Is this already known and expected? Would you
please provide some insights on what is happening here?</div>
</div>
</blockquote>
The reason why you see this difference is because with platform
threads all 1000 threads will be started and will wait
simultaneously, as releasing the monitor on wait() allows another
thread to enter it and wait() too. For virtual threads, since we
still pin on Object.wait(), we can only run as many threads as
workers in the FJP. So the code will behave like running in batches,
where after the first batch finishes waiting, the next one will run.
We actually compensate on Object.wait() until a max pool size of
256, which will give you around 4 batches, so that explains the
4x-5x you are seeing. If you increase the wait time you will see
this more clearly. This behavior will be fixed once we remove
pinning on Object.wait(). As for the difference between virtual
threads themselves against jdk21 I see a difference too. I'll need
to investigate a bit more to check exactly where the overhead is
coming from.<br>
<br>
<blockquote type="cite" cite="mid:CAOgKQu0qFvXOx2Cw5vJJS+V4pPctgEkbqhJerL8rzweo+Y1h=Q@mail.gmail.com">
<div dir="ltr">
<div>And also on the classloader side, I was wondering if there
are some plans to change classloader implementation (i.e to
use a Reentrantlock per class rather than synchronizing on an
object per class) </div>
<div>or do you expect the limitation of having native frames on
the stack causing thread pinning goes away rather soon and
hence no need to change classloader impl?</div>
</div>
</blockquote>
Note though that in this class loading/initialization deadlocks the
underlying issue is that we pin because there are native frames in
the stack, so replacing the synchronized with a j.u.c lock will
still lead to the same issue.<br>
<br>
Thanks,<br>
Patricio<br>
<blockquote type="cite" cite="mid:CAOgKQu0qFvXOx2Cw5vJJS+V4pPctgEkbqhJerL8rzweo+Y1h=Q@mail.gmail.com">
<div dir="ltr">
<div>Kind regards,</div>
<div>Masoud</div>
<div><br>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Thu, Feb 22, 2024 at
1:09 PM Alan Bateman <<a href="mailto:Alan.Bateman@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">Alan.Bateman@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On
21/02/2024 10:49, masoud parvari wrote:<br>
> :<br>
><br>
> And of course I am aware of Spring Boot 3.2+ releases.
The point of my <br>
> load testing was testing an application with lots of
contention on <br>
> objectmonitors rather than a setup where most of the
synchronized <br>
> blocks have been replaced by ReentrantLock.<br>
><br>
> So I would argue that for the mere purpose of testing
Loom's new <br>
> object monitor implementation, and making sure hanging is
not <br>
> happening, Spring boot 2.7.x is a better candidate than
3.2.x. I hope <br>
> this helps to clarify the testing's goal.<br>
><br>
<br>
I'm not familiar with the different versions of Spring but it
sounds <br>
like the 2.7.x has more uses of object monitors. That is
useful to know.<br>
<br>
Note that the EA builds have been refreshed to pick up recent
changes <br>
(and changes from main line). There is a change to the object
monitor <br>
implementation that makes blocked threads that are pinned
compete with <br>
the chosen successor when some thread exits a monitor. That
should help <br>
with some of the cases where resolving class references is
calling <br>
through the VM to load classes. Also one of your mails
mentioned that <br>
your JFR recordings didn't have all the expected
jdk.VirtualThreadPinned <br>
events. There are three cases where jdk.VirtualThreadPinned is
recorded, <br>
one of these missed the first EA build.<br>
<br>
-Alan<br>
</blockquote>
</div>
</blockquote>
<br>
</body>
</html>