Live data from Hacker News

Java Virtual Threads: A Case Study

infoq.com

161–170 of 199 posts

Re: Java Virtual Threads: A Case Study

#161
post #140

Earlier quoted context omitted.

Even though yes, in the end you have to map onto system threads, there are still quite a fee things you can do. But this is infeasible for Java, unfortunately. For example, in Erlang the entire VM is built around green threads with a huge amount of guarantees and mechanisms: https://news.ycombinator.com/item?id=40989995 When your entire system is optimized for green threads, the question of "it still needs to map ont…

I really don’t think it’s useful to be this nonspecific. You could give an example of what a Java greenlet cannot do or how it cannot be optimized, for example. If your whole point is actually just “I prefer the semantics of BEAM threads”, then just say that.

Those semantics are exactly what cannot be done in Java for many reasons (including legacy code etc.).

And yes, those semantics are important, but sadly most people stop at "yay we have green threads now" and then a null pointer exception kills their entire app, or the thread that handles requests, or...

Re: Java Virtual Threads: A Case Study

#162

Earlier quoted context omitted.

What problems exactly? Haskell has a few things that imo it does better than most languages in this area: - All IO is non-blocking by default. - FFI support for interruptible. - Haskell threads can be preempted externally - this allows you to ensure they never leak. Vs a goroutine that can just spin forever if it doesn't explicitly yield. - There are various stdlib abstractions for building concurrent programs in a c…

> Haskell threads can be preempted externally - this allows you to ensure they never leak. Vs a goroutine that can just spin forever if it doesn't explicitly yield. Goroutines are preemptible by the runtime (since https://go.dev/doc/go1.14#runtime ) but they're still not addressable or killable through the language itself.

The GHC runtime has lots of cool concurrency features.

Async exceptions as a way to pass messages (and kill threads!)

Allocation limits for threads.

Software Transactional Memory.

Re: Java Virtual Threads: A Case Study

#163
post #88

Earlier quoted context omitted.

OS Threads do not suck, they're great. But they are expensive to create as they require a syscall, and they're expensive to maintain as they consume quite a bit of memory just to exist, even if you don't need it (due to how they must pre-allocate a stack which apparently is around 2MB initially, and can't be made smaller as in most cases you will need even more, so it would make most cases worse). Virtual Threads are…

> and they're expensive to maintain as they consume quite a bit of memory just to exist, even if you don't need it (due to how they must pre-allocate a stack which apparently is around 2MB initially, I'm not familiar with windows, but this certainly isn't the case on Linux. It only costs 2mb-8mb of virtual address space, not actual physical memory. And there's no particular reason to believe the JVM can have a list o…

> And there's no particular reason to believe the JVM can have a list of threads and their states more efficiently than the kernel can.

Of course there is. The JVM is able to store the current stack for the Thread efficiently in the pre-allocated heap. Switching execution between Virtual Threads is very cheap. Experiments show you can have millions of VTs, but only a few thousand OS Threads.

I don't know why you think preemption is a big downside?! The JVM only suspends a Thread at safe points and those are points where it knows exactly when to resume. I don't believe there's any downsides at all.

Re: Java Virtual Threads: A Case Study

#164

Earlier quoted context omitted.

> So... What is it seeking to optimize? The goal is to maximize the number of tasks you can run concurrently, while imposing on the developers a low cognitive load to write and maintain the code. > Why did you need a thread pool before but not any more? You still need a thread pool. Except with virtual threads you are no longer bound to run a single task per thread. This is specially desirable when workloads are IO-b…

> why should you block a thread if creating gazillion threads on modern hardware is super cheap why not? I have transparency and debuggability what threads are running, can check stacktrace of each and what are they blocked on. virtual threads adds lots of magic under the hood, and if there will be some bug or lib in your infra with no vthreads support it is absolutely not clear how to debug it.

Each thread adds overhead.

Some usage types don’t care, some do.

From what I gather virtual threads are an alternative to “callback-hell” (js) or async coloring (python).

Re: Java Virtual Threads: A Case Study

#165
post #128

Earlier quoted context omitted.

What patterns does async/await solve which virtual threads don’t?

"Green Threads" as implemented in Java is a solution that solves only a single problem - blocking/multiplexing. It does not enable easy concurrency and task/future composition the way C#/JS/Rust do, which offer strictly better and more comprehensive model.

What do you mean? It implements the Future/Task interface and you can definitely use that. In fact you can’t tell the difference from a virtual thread vs a platform one, and it’s available everywhere. I for one thinks it’s much easier to use than the async/await pattern as I don’t need any special syntax to use it.

Re: Java Virtual Threads: A Case Study

#166
post #142
post #128

Earlier quoted context omitted.

What patterns does async/await solve which virtual threads don’t?

If you need to be explicit about thread contexts because you're using a thread that's bound to some other runtime (say, a GL Context) or you simply want to use a single thread for synchronization like is common in UI programming with a Main/UI Thread, async/await does quite well. The async/await sugar ends up being a better devx than thread locking and implicit threading just doesn't cut it. In Java they're working o…

What’s stopping you from using a single thread for synchronization?

Re: Java Virtual Threads: A Case Study

#167
post #63

Virtual threads do one thing: they allow creating lots of threads. This helps throughput due to Little's law [1]. But because this server here saturates the CPU with only a few threads (it doesn't do the fanout modern servers tend to do), this means that no significant improvements can be provided by virtual threads (or asynchronous programming, which operates on the same principle) while keeping everything else in t…

I guess at least their work has confirmed what we probably already knew intuitively: if you have CPU-intensive tasks, without waiting on anything, and you want to execute these concurrently, use traditional threads. The advice "don't use virtual threads for that, it will be inefficient" really does need some evidence. Mildly infuriating though that people may read this and think that somehow the JVM has problems in i…

I'll put it this way: to benefit from virtual threads (or, indeed, from any kind of change to scheduling, such as with asynchronous code) you clearly need 1. some free computational resources and 2. lots of concurrent tasks. The server here could perhaps have both with some changes to its deployment and coding style, but as it was tested -- it had neither. I'm not sure what they were hoping to achieve.

Re: Java Virtual Threads: A Case Study

#168

Earlier quoted context omitted.

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 d…

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...

Re: Java Virtual Threads: A Case Study

#169
post #50
post #39

Are these Virtual Threads the feature that was previously known as “Project Loom”? Lightweight threads, more-or-less equivalent to Go’s goroutines?

Yes, at EclipseCon 2022 an Oracle manager working on the Helidon framework presented their results replacing the Helidon core, which was based on Netty (and reactive programming) with Virtual Threads (using imperative programming). [1]. Unfortunately the slides from that presentation were not uploaded to the conference site, but this article summarizes [2] the most significant metrics. The Oracle guy claimed that by…

I wanted to know more, and it seems this is the presentation: https://www.youtube.com/watch?v=aYY04D4_OQA

Re: Java Virtual Threads: A Case Study

#170
post #138
post #104

Earlier quoted context omitted.

As an Erlang person, from reading about Java's Virtual Threads, it feels like it should get a significant portion of the Erlang concurrency story. With virtual threads, it seems like if you don't hit gotchas, you can spawn a thead, and run straight through blocking code and not worry about too many threads, etc. So you could do thread per connection/user chat servers and http servers and what not. Yes, it's still sha…

Erlang's concurrency story isn't green threads. It's (with caveats, of course): - a thread crashing will not bring the system down - a thread cannot hog all processing time as the system ensures all threads get to run. The entire system is re-entrant and execution of each thread can be suspended to let other threads continue - all CPU cores can and will be utilized transparently to the user - you can monitor a thread…

Neither an error nor a recovered-from panic will cause a Go program to crash; only an unrecovered panic does that.

The bigger problem with Go in this regard is how easy it is to cause a panic thanks to nil.

Post reply on HN