<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>