Live data from Hacker News

Java Virtual Threads: A Case Study

infoq.com

131–140 of 199 posts

Re: Java Virtual Threads: A Case Study

#131

Earlier quoted context omitted.

Why is an async model better than using OS threads for an I/O bound workload? The OS is doing async stuff internally and shielding the complexity with threads. With virtual threads this work has shifted to the JVM. Can the JVM do threads better than the OS?

"Why is an async model better than using OS threads for an I/O bound workload?" Because evented/callback-driven code is a nightmare to reason about and breaks lots of very basic tools, like the humble stack trace. Another big thing for me is resource management - try/finally don't work across callback boundaries, but do work within a virtual thread. I recently ported a netty-based evented system to virtual threads an…

[deleted]

Re: Java Virtual Threads: A Case Study

#132
post #128
post #110

Earlier quoted context omitted.

There is overlap but they really don't solve the same problem. Cooperative threading has its own advantages and patterns that won't be served by virtual threads.

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.

Re: Java Virtual Threads: A Case Study

#133
post #101

Earlier quoted context omitted.

> and just use java.net.HttpClient. No.

it might be obvious to others, but why the 'No'?

The standard http client doesn’t have as great of UX as other community libs. Most of us (including me) don’t like to use it.

That being said, imo you can’t call something equivalent when doing a bunch of spring magic. This disregards that OPs logic isn’t equivalent at all. It waits for each future 1 by 1 instead of doing something like CompletableFuture.allOf or in JS: Promise.all.

Re: Java Virtual Threads: A Case Study

#134
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?

They're not equivalent to Go's goroutines.

Go's goroutines are preemptive (and Go's development team went through a lot of pain to make them such).

Java's lightweight threads aren't.

Java's repeating the same mistakes that Go made (and learned from) 10 years ago.

Re: Java Virtual Threads: A Case Study

#135

Earlier quoted context omitted.

The OS scheduler is still there (for the carrier threads), but now you've added on top of that FJ pool based scheduler overhead. Although virtual threads don't have the syscall overhead when they block, there's a new cost caused by allocating the internal continuation object, and copying state into it. This puts more pressure on the garbage collector. Context switching cost due to CPU cache thrashing doesn't go away…

The study says there's surprising performance problems with Java's virtual thread implementation. Their test of throughput was also hilarious, they put 2000 OS threads vs 2000 virtual threads: most of the time OS threads don't start falling apart until 100k+ threads. You can architect an application such that you can handle 200k simultaneous connections using platform-thread-per-core, but it's harder to reason about…

> Except it's not a context switch? You're jumping to another instruction in the program, one that should be very predictable. You might lose your cache, but it will depend on a ton of factors.

Java virtual threads are stackful; they have to save and restore the stack every time they mount a different virtual thread to the platform thread. They do this by naive[0] copying of the stack out to a heap allocation and then back again, every time. That's clearly a context switch that you're paying for; it's just not in the kernel. I believe this is what the person you're replying to is talking about.

[0] Not totally naive. They do take some effort to copy only subsets of the stack if they can get away with it. But it's still all done by copies. I don't know enough to understand why they need to copy and can't just swap stack pointers. I think it's related to the need to dynamically grow the stack when the thread is active vs. having a fixed size heap allocation to store the stack copy.

Re: Java Virtual Threads: A Case Study

#136
post #73

Earlier quoted context omitted.

Just a side note, async JDBC was a thing way before Loom came about, and it failed miserably. I'm not sure why, but my guess would be is that most enterprise software is not web-scale, so JDBC worked well as it was. Also, all the database vendors provided their drivers implementing the JDBC API - good luck getting Oracle or IBM contribute to R2DBC.. (Actually, I stand corrected: there is an Oracle R2DBC driver now -…

R2DBC allows to efficiently maintain millions of connections to the database. But what database supports millions of connections? Not postgres for sure, and probably no other conventional database. So using reactive JDBC driver makes little sense, if you're going to use 1000 connections, 1000 threads will do just fine and bring little overhead. Those who use Java, don't care about spending 100 more MB of RAM when the…

Reactive drivers were not about 1000 connections, they were about reusing a single connection better, by queuing a little bit more efficient over a single connection. Reactive programming is not about parallelism, it’s about concurrency.

Re: Java Virtual Threads: A Case Study

#137
post #134
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?

They're not equivalent to Go's goroutines. Go's goroutines are preemptive (and Go's development team went through a lot of pain to make them such). Java's lightweight threads aren't. Java's repeating the same mistakes that Go made (and learned from) 10 years ago.

Virtual threads could be scheduled pre-emptively but currently the scheduler will wait for some kind of thread sleep to schedule another virtual thread. That's just a scheduler implementation detail and the spec is such that a time slice scheduler could be implemented.

Re: Java Virtual Threads: A Case Study

#138
post #104
post #86

Earlier quoted context omitted.

Erlang, not Go, should be the obvious choice for concurrency, but it's impossible to retrofit Erlang's concurrency onto existing systems.

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 and if it crashes you're guaranteed to receive info on why and how it crashed

- immutable data structures play a huge part of it, of course, but the above is probably more important

That's why Go's concurrency is not that good, actually. Goroutines are not even half-way there: an error in a goroutine can panic-kill your entire program, there are no good ways to monitor them etc.

Re: Java Virtual Threads: A Case Study

#139
post #118
post #86

Earlier quoted context omitted.

Erlang, not Go, should be the obvious choice for concurrency, but it's impossible to retrofit Erlang's concurrency onto existing systems.

Isn't that Akka?

Akka is heavily inspired by Erlang, but the underlying system/VM has to provide certain guarantees for actual Erlang-style concurrency to work: https://news.ycombinator.com/item?id=40989995

Re: Java Virtual Threads: A Case Study

#140

Earlier quoted context omitted.

This take sounds reasonable to me. But I'm not an expert, and I'd be curious to hear an opposing view if there's one.

Greenlets ultimately have to be scheduled onto system threads at the end of the day unless you have a lightweight thread model of some sort supported by the OS, so it’s a little bit misleading depending on how far down the stack you want to think about optimizing for greenlets. You could potentially have a poor implementation of task scheduling for some legacy compatibility reason, however. I guess I’d be curious abo…

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 onto OS threads" loses its significance

Post reply on HN