William,

On 8/24/23 09:50, William Crowell wrote:
I did some performance testing with virtual threads on Apache Tomcat
11.0.0-M10 and JDK 21 (21+35-2513).  I have a simple REST service
using Spring 6.0.11 that does an insert into MySQL 8.0.32.

I have 3 separate boxes all running Rocky Linux 9.2 on AWS
(t3a.xlarge which is 4 vCPUs and 16GiB RAM):

1) An application server running Tomcat 11.0.0-M10 with JDK 21

2) MySQL 8.0.32

3) JMeter 5.6.2

I know that JDK 21 is nowhere near GA, but I got some interesting
results.  I did 10 test runs with useVirtualThreads=“true”, and 10
test runs without virtual threads (the default).  Each run used 1000
threads in JMeter for about 3 minutes and 20 seconds for a ramp up
time of 3 seconds.

What I found was using platform threads performed at least twice as
fast as virtual threads.  Maybe I am interpreting the results wrong,
but this is what I found consistently across each test.

Again, I realize that performance is not the only goal of virtual
threads.  Just my observations.

This is "interesting", for some values of interesting.

I'd be interested in what the application was doing. Virtual Threads seem to be aimed at things like Web Application Containers where there is a lot of wasted time in a thread's execution waiting on I/O (blocking). If you ignore the application's workload (hah!), the application server is almost entirely occupied with (a) reading the request and (b) writing the response. There is almost no "computation time" and so Virtual Threads make a whole lot of sense.

Once inside the application, that may not be true.

From what little reading I have done on Virtual Threads, there are some poison pills in there depending upon application design. For example, if your thread blocks while inside a synchronized{} block, then your Virtual Thread is "pinned" and will NOT be un-mounted from the platform thread during the blocking operation. So all of that high-speed context-switching and magic that VT is supposed to provide goes completely out the window when you used to have 200 threads with maybe 8 of them actually running at once but swapping-out preemptively, but now you have 200 virtual threads with 8 of them running at once, but of the 8 running at once, several of them are stopped dead unable to make any progress.

At $work, we have plenty of read-through cache routines like this:

private Object somethingBigLock = new Object();
private SomethingBig big = null;
public Object getSomethingBigFromDatabase() {
    synchronized(somethingBigLock) {
      if(null == big) {
          big = reallyGetSomethingBigFromDb(); // Non-trivial
      }

      return big;
    }
}

Even if reallyGetSomethingBigFromDb() is mostly blocking on I/O -- e.g. waiting for the db to respond to a query -- it will consume one of your platform threads and lock it up, leaving fewer platform threads available to do the other work.

Without a critical analysis of your application and the libraries it uses, it's hard to tell if what you are observing is that "virtual threads are not as fast as regular threads" or "your application is an anti-pattern for Virtual Threads". My guess is that your application and/or the libraries you are using need to be re-written so they no longer use "classic" synchronization and instead use things like ReentrantLock for a similar purpose to play-nice with VT. Or you can wait for the (likely) inevitable improvement of the JVM which allows for threads holding monitors to be unmounted from platform threads. My guess is that is in the future for the JVM.

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to