Rainer,

On 3/20/24 13:33, Rainer Jung wrote:
Am 20.03.24 um 18:17 schrieb Christopher Schultz:
Rainer,

Thanks for writing this up.

On 3/20/24 07:22, Rainer Jung wrote:
I wanted to share an observation and I hope the things are correct how I am describing them. Maybe things have already improved and I am not aware of it, hints welcome.

Part of JEP 425 (Project Loom, Java virtual threads) discusses how to handle observability of virtual threads from inside the JVM and tooling.

The final outcome is, that virtual threads are not included in the typical JVM APIs which one can use to observe threads, like enumerating them or accessing the stacks of individual threads. As a consequence, also jstack and "kill -QUIT" do not show virtual threads at all, not even when they are attached to a native thread and executing code.

O_O

There is one single method to help with observability of virtual threads

https://docs.oracle.com/en/java/javase/21/docs/api/jdk.management/com/sun/management/HotSpotDiagnosticMXBean.html#dumpThreads(java.lang.String,com.sun.management.HotSpotDiagnosticMXBean.ThreadDumpFormat)

which dumps a full thread dump to a file. Of course that is by no means appropriate, if you want to do a fine grained observation. At least you can choose to write a json structure instead of a hard to parse text format, but that's it.

Boy, that's a real miss from the JVM team. I'm surprised that they have overlooked this. I don't see a real reason that a Virtual Thread would be treated any differently than a regular thread.

The JEP hints at "since thre could be millions of virtual threads it makes no sense to support them in the existing JMX APIs". I don't by this extremely simplistic reasoning.

:/

Furthermore, the "dump to file" method they provided does not contain any locking information you usually expect in a thread dump.

+1

For instance I am often using a tool, that inspects our RequestProcessors to find long running requests and then retrieves the list of Java threads as ThreadInfo objects to find the one executing the request and finally retrieves the stack of that request from the JVM. Such an approach is no longer possible. Almost all of JMX does not show any info about virtual threads.

It also seems Tomcat no longer uses a pool when a connector is configured to use virtual threads. So there are no metrics like currentThreadCount or currentThreadsBusy.

When using virtual threads, the number of requests is the same as the number of threads, since each request -> new Virtual Thread.... though I think the request-count is only incremented when the request has completed, so maybe there are threads running that can't be counted (yet).

But I understand that you were hoping to get some information about these threads and though maybe Tomcat's metrics could help. I guess not really.

But thread-busy count is the same as in-flight-request count. And current thread count is the same as in-flight-request count as well.

I guess this also limits the use of some manager features and probably also the StuckThreadsDetectionValve when combined with virtual threads.

Most likely. I'm fairly sure that uses the "usual Thread-walker things" which you are reporting do not work any more with VTs.

What JVM are you using for your investigations?

Zulu 21, but I expect the other OpenJDK variants to behave the same way. It mostly comes out of the JEP.

Of course Tomcat has solved most of the problems, that virtual threads want to solve, by doing the hard work of using the NIO and NIO2 APIs. So virtual threads are probably not that important for us. But we should be aware of the observability deficiencies whenever we would discuss whether we could switch from NIO or NIO2 to virtual threads to simplify connector code in some distant future.

+1

I've been enthusiastically talking with markt about dropping all that nasty NIO stuff and "going back to BIO with virtual threads" which, at this point, is mostly a threat and not a promise. But if VTs really deliver everything they are claiming to deliver, then it may be possible to go back to BIO as long as servlet-async is retired. And I'm not holding my breath on that one.

There was an interesting talk at FOSDEM about the current limitations of the virtual thread implementation. They have several situations where they switch over to blocking. I think for instance file I/O and also some types of locks they can not yet handle well.

Yes, these are known issues. Specifically, synchronized blocks and virtual threads don't play well together, which is why Tomcat recently converted many synchronized { ... } to use ReentrantLocks, which DO work with (today's) VTs.

They have some improvements in the pipeline, but I think one would at least wait for those. And hopefully they improve the observability in the meantime.

+100

I wish I had known this type of problem at FOSDEM so I could have directly talked to the OpenJDK devs there.

There's always next year :)

-chris

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

Reply via email to