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