Re:Java Virtual Threads: A Case Study
by frant-hartm on Wednesday July 17, 2024 @03:54AM
(#40983474)
What do you mean by context switching?
My understanding is that virtual threads mostly eliminate context switching - for N CPUs JVM creates N platform threads and they run virtual threads as needed. There is no real context switching apart from GC and other JVM internal threads.
A platform thread picking another virtual thread to run after its current virtual thread is blocked on IO is not a context switch, that is an expensive OS-level operation.
Re:Java Virtual Threads: A Case Study
by anonymousDan on Wednesday July 17, 2024 @04:59AM
(#40983799)
Does Java's implementation of virtual threads perform any kind of work stealing when a particular physical thread has no virtual threads to run (e.g. they are all blocked on I/O)?
Re:Java Virtual Threads: A Case Study
by mike_hearn on Wednesday July 17, 2024 @05:59AM
(#40984155)
It does. They get scheduled onto the ForkJoinPool which is a work stealing pool.
"they run virtual threads as needed" - so when one virtual thread is no longer needed and another one is needed, they switch context, yes?
Re:Java Virtual Threads: A Case Study
by frant-hartm on Wednesday July 17, 2024 @09:10AM
(#40985511)
This is called mounting/un-mounting and is much cheaper than a context switch.
This is a type of context switch. You are saying dollars are cheaper than money.
It's been a really long time since I dealt with anything this low level, but in my very limited and ancient experience when people talk about context switching they're talking specifically about the userland process yielding execution back to the kernel so that the processor can be reassigned to a different process/thread. Naively, if the JVM isn't actually yielding control back to the kernel, it has the freedom to do things in a much more lightweight manner than the kernel would have to.
So I think it's meaningful to define what we mean by context switch here.
When a real thread is allocated from a virtual thread to another, the JVM needs to save into the heap the stack of the first virtual thread and restore from the heap the stack of the second virtual thread, see slide 13 of [1]. This is in fact called mounting/unmounting as already pointed out, and occurs via Java Continuation, but from the JVM perspective this is a context switch. It's called JVM and the V stands for Virtual, so yes, it's not the kernel doing it, but it's happening, and it's more frequent the more virtual threads you have in your application.
[1] https://www.eclipsecon.org/sites/default/files/slides/JavaLo...
swapcontext(3) is a userland context switch, and is named so.
The JVM will need to do context switching when reallocating the real thread that is running a blocked virtual thread to the next available virtual thread. It won't be CPU context switching, but context switching happens at the JVM level and represents an effort.
Re:Java Virtual Threads: A Case Study
by frant-hartm on Wednesday July 17, 2024 @09:10AM
(#40985500)
Ok. This JVM-level switching is called mounting/un-mounting of the virtual thread and is supposed to be several orders of magnitude cheaper compared to normal context switch. You should be fine with millions of virtual threads.
This gives the chance to the JVM to use real threads more efficiently, avoiding that threads remain unused while waiting on I/O (e.g. a response from a stream). As soon as the JVM detects that a physical thread is blocked on I/O, a semaphore, a lock or anything, it will reallocate that physical thread to running a new virtual thread. This will reduce latency, context switch time (the switching is done by the JVM that already globally manages the memory of the Java process in its heap) and will avoid or at least largely reduce the chance that a real thread remains allocated but idle as it's blocked on I/O or something else.