EA builds with changes to object monitor implementation to avoid pinning with virtual threads

masoud parvari masoud.parvari at gmail.com
Tue Feb 27 20:28:34 UTC 2024


Hi Alan,
Thanks for the second EA of new object monitor implementation. I have been
testing it for the last few days.

I am happy to confirm the hanging is not happening anymore on my side. I
also observed improvements on receiving "jdk.VirtualThreadPineed" events.
In my setup I only get "jdk.VirtualThreadPineed" events in Classloading
scenarios or object.wait() within synchronized blocks which are expected as
far as I know.

I have been testing only with LockingMode=1 (default) for now. I will test
LockingMode=2 and let you know if any issues come up.

My current setup is heavily using synchronized blocks (lots of caches) and
lots of concurrent class loadings, as well as object.wait() in few of the
application's hot paths.
So far, hanging hasn't been observed which is really good news.
Congratulations to you and the team.

I was triggered by your explanation about how new implementation tries to
avoid hanging by calling a chosen successor upon exiting synchronized block
and tried to check performance of new build against
virtual thread impl in 21 and also platform threads in current build. This
is the sample code:

public class VirtualThreadPerformanceTest {

    public static void main(String[] args) throws InterruptedException {
        int size = 1000;
        test(false, size);
        test(true, size);
    }

    private static void test(boolean isVirtual, int size) throws
InterruptedException {
        ExecutorService executorService = isVirtual == true ?
Executors.newVirtualThreadPerTaskExecutor()
            :
Executors.newThreadPerTaskExecutor(Thread.ofPlatform().factory());
        CountDownLatch latch = new CountDownLatch(size);
        long start = System.currentTimeMillis();
        Object object = new Object();
        for (int i = 0; i < size; i++) {
            executorService.submit(() -> {
                synchronized (object) {
                    try {
                        object.wait(100);
                    } catch (InterruptedException e) {
                        //do nothing;
                    }
                }
                latch.countDown();
            });
        }
        synchronized (object) {
            object.notifyAll();
        }
        latch.await();
        long duration = System.currentTimeMillis() - start;
        System.out.println((isVirtual? "Virtual" : "Platform") + " took " +
duration + " milliseconds");
    }
}

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?

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

Kind regards,
Masoud


On Thu, Feb 22, 2024 at 1:09 PM Alan Bateman <Alan.Bateman at oracle.com>
wrote:

> On 21/02/2024 10:49, masoud parvari wrote:
> > :
> >
> > And of course I am aware of Spring Boot 3.2+ releases. The point of my
> > load testing was testing an application with lots of contention on
> > objectmonitors rather than a setup where most of the synchronized
> > blocks have been replaced by ReentrantLock.
> >
> > So I would argue that for the mere purpose of testing Loom's new
> > object monitor implementation, and making sure hanging is not
> > happening, Spring boot 2.7.x is a better candidate than 3.2.x. I hope
> > this helps to clarify the testing's goal.
> >
>
> I'm not familiar with the different versions of Spring but it sounds
> like the 2.7.x has more uses of object monitors. That is useful to know.
>
> Note that the EA builds have been refreshed to pick up recent changes
> (and changes from main line). There is a change to the object monitor
> implementation that makes blocked threads that are pinned compete with
> the chosen successor when some thread exits a monitor. That should help
> with some of the cases where resolving class references is calling
> through the VM to load classes. Also one of your mails mentioned that
> your JFR recordings didn't have all the expected jdk.VirtualThreadPinned
> events. There are three cases where jdk.VirtualThreadPinned is recorded,
> one of these missed the first EA build.
>
> -Alan
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20240227/c44aeb7e/attachment-0001.htm>


More information about the loom-dev mailing list