14 ms·
State of Loom
- MrBuddyCasino 6y ago> A virtual thread is a Thread — in code, at runtime, in the debugger and in the profiler. To explain: if you debug async code on Kotlin right now, you cannot single-step in a debugger, because the debugger attaches to a thread. But coroutines get scheduled on different threads all the time! I wonder what this means for ThreadLocals and Locks? Will they work as before? If so, that is huge! Because locks don't work with async code either, for obvious reasons. The consequence is that the whole ecosystem is split in two parts! You cannot just use a Guava cache in Kotlin coroutine-based code. If Loom manages to avoid all of this, this is fantastic news.
- pron 6y ago> I wonder what this means for ThreadLocals and Locks? Will they work as before? Yes. You can try that today: http://jdk.java.net/loom http://jdk.java.net/loom
- MrBuddyCasino 6y agoThis is outstanding. They solved the „what color is your function“ problem! The Rust ecosystem has a completely separate std-lib just for async. I think there is one other language that managed to avoid that problem too by using compile-time magic [0]. [0] https://github.com/ziglang/zig/issues/1778 https://github.com/ziglang/zig/issues/1778
- The_rationalist 6y agoKotlin has solved colouring before loom -> https://medium.com/@elizarov/how-do-you-color-your-functions-a6bb423d936d https://medium.com/@elizarov/how-do-you-color-your-functions... Go was the first to solve colouring but they have it seems a less type safe solution
- pron 6y agoKotlin, like C#, has a two-colour, double API system for synchronous code on threads and on coroutines.
- The_rationalist 6y agoI don't understand, you can call a coroutine from a synchronous function and call a normal or suspend function from a suspending one. By colorless we mean that you can use a suspend return type directly and not through the ugliness of a promise. Kotlin did choose to have the suspend keyword but it's just an explicit type, kotlin could have had no suspend keyword and be officially colorless, it is technically colorless and is I believe the best of both worlds
- pron 6y ago> I don't understand, you can call a coroutine from a synchronous function and call a normal or suspend function from a suspending one. Not without a syntactic distinction, and not without losing the performance characteristics you want coroutines to begin with. > By colorless we mean that you can use a suspend return type directly and not through the ugliness of a promise. That's not colourless. Colourless means that there is no syntactic distinction between sleep and delay. Two subroutines that mean the same but have a different syntactic colour. > kotlin could have had no suspend keyword and be officially colorless, It could not. You'd need to control the JDK to do that, or depend on class reloading, or pay a very high price in performance. Not to mention that it still wouldn't help when calling Java code (directly or indirectly) nor would it change how, say, JFR observes your program. The problem is that Kotlin has very little influence over the platforms it targets -- Java, Android, JS and LLVM (well, maybe it has some influence over Android) -- and so must do its best to implement its functionality on top. > I believe the best of both worlds We don't want two worlds. We don't need two worlds. We want one that behaves as it should.
- MrBuddyCasino 6y agoGolang occupies an interesting spot here. They never had to migrate from a predominantly blocking, thread-based ecosystem to async. Does Golang really have two colors, is explicit threading a thing (I honestly don't know)? Or is it really just one color, namely the async one?
- aliceryhl 6y agoI mean, just because someone made a crate with std in the name doesn't make it another standard library. The actual standard library is still useful in async, as only the things that does IO or otherwise needs to sleep requires special handling.
- grogers 6y agoI know of only one other, in erlang writing code to "just block" works as it should. In erlang processes are even fully preemptible too, not just at possibly-blocking points, although native code blocks the OS thread like in loom.
- toast0 6y agoFrom what I understand, Erlang only preempts at function entry or exit, or at marked points in NIFs (C code). Because functional programming requires loops to be written as recursive function calls, you can't do too much without calling/leaving a function, so a process can't avoid premption.
- kasperni 6y ago> The consequence is that the whole ecosystem is split in two parts! Which it might continue to be. As Kotlin needs to support other backends than just the JVM.
- sgt 6y agoWhy does it absolutely need to? I thought the purpose of Kotlin was to primarily be a JVM language.
- kasperni 6y agoIt started out with just Kotlin/JVM. But now you also have Kotlin/Native and Kotlin/JS. Being multi-platformed has some drawbacks, for example, that it can be difficult to expose certain abstractions that are only supported on a subset of the platforms.
- sgt 6y agoThanks, I didn't know that. It seems like that would slow down the project a bit.
- The_rationalist 6y agoKotlin can to lower it's IR to platform specifically intrinsics and have platform exclusive features to an extent. E.g inline classes are currently only available on the JVM
- kasperni 6y ago> Kotlin can to lower it's IR to platform specifically intrinsics and have platform exclusive features to an extent. As pointed out elsewhere this won't really help you in any way in this situation.
- GordonS 6y agoHmm, the most popular C# IDEs (Visual Studio and Rider) don't have this problem - you can single step when debugging async code. Is there something in particular about the JVM that makes it more difficult, or is it just that the work hasn't been done yet for some reason?
- yrio 6y agoI don't know about single step when debugging, but it seems intelligible stack trace for async code is available only recently, starting with .NET Core 2.1 https://stackoverflow.com/questions/15410661/is-it-possible-to-get-a-good-stack-trace-with-net-async-methods https://stackoverflow.com/questions/15410661/is-it-possible-...
- GordonS 6y agoIt was a long while back, so I can't be sure, but I seem to recall single step debugging and good stack traces being available since the first days of async/await, although there are some ways you can get yourself into situations where stack traces are near to worthless.
- ceronman 6y agoThis is my favorite JVM project and I think it's going to be huge! This model of concurrency is so much better than the async/await model used by many other languages. No more colored functions [1], or worse Completable<Future>, promises et al. Nice stacktraces, debuggers that work plus no need for thread pools anymore. I can't wait for this to be ready for production. Only drawback seems to be when calling native code. I guess it's the same problem that Golang has. Good thing is that the Java ecosystem is not that dependent on native stuff, so I think it's a fair tradeoff to make. [1] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
- anonymoushn 6y agoWill virtual threads be copyable?
- mrkeen 6y ago> No more colored functions [1] That's a property of the function, whether or not you want the type system to help you with it. I can call a function myRedFunction, but if it calls a blue function, it's blue. > or worse Completable<Future> What is this? Future<Result> f = e.submit(() -> { ... return result; }); // spawns a new virtual thread > This model of concurrency is so much better than the async/await mode ThreadFactory tf = Thread.builder().virtual().factory(); ExecutorService e = Executors.newUnboundedExecutor(tf); Future<Result> f = e.submit(() -> { ... return result; }); // spawns a new virtual thread ... Result y = f.get(); // joins the virtual thread I don't get it. This just looks like async/await (submit/get) with extra steps. Why not just write Future<Result> f = async ( ... result; ) Result y = await (f);
- pron 6y ago> That's a property of the function, whether or not you want the type system to help you with it. The problem is that in, say, C# or Kotlin, subroutines with the same semantics come in two different colours. The type system "helps" you distinguish between things that aren't meaningfully distinguishable. > I don't get it. This just looks like async/await (submit/get) with extra steps. You only need to submit if you want to do stuff in parallel and then join (also, there are no extra steps). The analogue to: var a = await doA(); var b = await doB(); is just: var a = doA(); var b = doB();
- eiopa 6y agoThis reminds me a lot of python’s gevent. I often wish the language had adopted it instead of the C#-like await async, since it’s just more straightforward.
- dehrmann 6y agogevent has some serious drawbacks. Stack traces are incomprehensible, it works by monkey patching existing code, and it falls apart if you have a blocking operation gevent can't make async. Loom is a bit like monkey patching, but at the VM level, so I expect it to be much more stable.
- jpgvm 6y agoIt's worth mentioning those drawbacks are implementation problems, not soundness or ergonomic problems with the model itself. I would consider myself a pretty harsh critic of Python but even I appreciate the elegance of the gevent approach to concurrency.
- doctor_eval 6y agoI was reading about Go threads just the other day and the article mentioned that Go uses green threads because they are more efficient. I thought this was weird because IIRC Java 1.0 used green threads in Linux and it was a big deal when they moved to OS threads. I’ve long believed that the IT world moves in cycles but this is a very clear example of exactly that. Java has gone from green threads to Posix threads and now back to green threads. I do think it’s awesome (I love goroutines) and Threads in Java have become a but of a nightmare, made a little easier with executors and CompletableFutures. So this further improvement is great news. But still... call me when the builder pattern is dead.
- dullgiulio 6y agoAs the article explains (I know it's hard to comment after actually reading), Java moved away from using several green threads on top of a single system thread. What Loom and Go do is to schedule green threads on a bunch of system threads and spawn more system threads when they get blocked doing synchronous system calls.
- doctor_eval 6y agoNo need for snark, I did read the article. I was just pointing out the irony that it was a big deal when the JVM moved away from green threads and now it’s a big deal when it moves back. It’s a comment on the hype cycle. And, as I said in my OP, it’s a good change and I’m happy to see it. (And if you want to be pedantic, IIRC the green threads were originally mapped to the Java process, not a thread, because threads were either unavailable or immature in Linux when Java 1 came out; I can’t remember which)
- codr7 6y agoYou're missing the point, which is what the person replying was trying to explain. We're not simply going back and forth, we're learning from past experience and improving implementations. The green threads on the JVM were not the same kind as green threads in Go (and Loom), they would block on IO. Can't speak for Loom, but Go automagically reschedules your green thread when it blocks which allows other threads to run while waiting. The point is they weren't rescheduled when they would block in the JVM, every process has a main thread.
- chewbacha 6y agoHmm I love having cake... ...and eating it too
- Igelau 6y agoAnyone else disappointed this wasn't about Lucasarts Loom (1990)?
- davidjhall 6y agoHave to admit - I was excited to think this was about a SCUMM update or maybe a sequel.
- aidenn0 6y agoYou mean the latest masterpiece of fantasy storytelling from Lucasfilm's™ Brian Moriarty™?
- e12e 6y ago> A server can handle upward of a million concurrent open sockets, yet the operating system cannot efficiently handle more than a few thousand active (non-idle) threads. Does anyone have a reference to some up to date notes on the state of scalability of Linux and/or free-/dragonfly-bsd scalability at the process level? I don't doubt processes are a bit heavy for scaling to a million active threads of execution - but it'd be nice to see what one could expect on a low end server (say 16 cores, 64gb ram) today?
- zokier 6y agoI'd also be curious about this. C10k was a problem at the turn of the century but world has changed a lot since, both in terms of hardware and kernel. Best reference I could easily find was this experiment that had 100k connections to mysql which has thread per connection model. Seems to handle it well https://www.percona.com/blog/2019/02/25/mysql-challenge-100k-connections/ https://www.percona.com/blog/2019/02/25/mysql-challenge-100k...
- MattTse 6y agoAnyone else read this, and read it as google's Project Loon, and wonder what java has to do with it?
- jmartrican 6y agoI been waiting for this project for a while. I saw an amazing demo of this on youtube video. In the demo a regular Jetty server running a simple endpoint that slept for 1 sec was DOSd with multiple concurrent requests. You can see as the number of concurrent requests increased, the execution time increased. The presenter then changed the code of the Jetty server to create a new Fiber vs a Thread. Then reproduced the test and this time there was no increase in execution time. What I really like about this project is that we can keep Spring MVC applications in non-reactive form. Spring MVC came out with reactive framework for implementing APIs. But I'm not a fan of this style for a few reasons, plus there is millions of LOC doing it the non react implementation. By utilizing project Loom, we do not have to switch over to the Spring reactive way, and we can increase the performance of existing code. EDIT: Here is the video: https://www.youtube.com/watch?v=Csc2JRs6470 https://www.youtube.com/watch?v=Csc2JRs6470: - he goes into Loom at 19:30. - he goes into the demo at 24:00.
- artemonster 6y agoCan Loom be used to simulate RTL & verification language on top of that (similar to SV or e)? I mean practically (since theoretically the answer is yes)
- elric 6y agoIn case anyone else is confused about some of the internal links appearing to be broken (e.g. the Scope Variables link), the content is on the second page.
- pizlonator 6y agoThis is great. If I grok right this is basically the best of native threads and the best of green threads put together. I think I proposed this at a crazy idea talk at VEE a long ass time ago (10 years or more). It’s still a good idea but I guess not crazy anymore.
- jayd16 6y agoSeems fine but I'm confused by the async/await hate. At least in C# it seems to me thee is already a superset of Loom through async/await. Thread.startVirtualThread(() -> {}); Starts a new virtual thread that will run a synchronous method. Ok cool. C# already has: Task.Run(()=>{}) This will run synchronously on the shared thread pool. Tasks are futures and can return objects. Same as the Loom proposal. Optionally you can decide to opt into the await unboxing sugar by adding async to your method signature. There's arguably some double dipping with the async keyword on a method. It allows the await keyword to be used inside the method but also forces the caller into a different calling style. You can argue this shows API intent for cooperative threading. That said, you can still use async and sync interchangeably. The syntax seems very similar to me. Is there something else going on in Loom that I'm missing? Is it a matter of how the virtual threads are scheduled/preempted vs how other languages with async/await schedule their tasks?
- balfirevic 6y agoThe point is that you don't have to write code in a different way if you want to avoid blocking an OS thread on IO operation.
- jsiepkes 6y agoMaybe I don't understand correctly what your saying but "Task.Run" just schedules something on a normal (kernel) thread by using a common thread pool. The Java equivelant is probably "CompletableFuture.runAsync" which does the same thing. Loom with "Thread.startVirtualThread" will run something on a userland / green thread (ie. not a kernel thread so no context switching and blocking it "costs" practically nothing). async-await is actually a subset of wat Loom does in the sense that Loom allows for far more then just async-await. Most of the "hate" for async-await is probably because it leads to the "what color is your function" [1] problem. [1] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
- dang 6y agoSee also: https://news.ycombinator.com/item?id=17646169 https://news.ycombinator.com/item?id=17646169 from 2018 https://news.ycombinator.com/item?id=15599854 https://news.ycombinator.com/item?id=15599854 from 2017 https://news.ycombinator.com/item?id=23194215 https://news.ycombinator.com/item?id=23194215 - 3 comments from a few days ago
- joobus 6y agoThe project has been in development for 3 years, only "early access" binaries are available now, and the parent article has multiple TBD notes. It's going to be another few years before this is released, IMO.
- vips7L 6y agoJava moves slow on purpose because they have strict backwards compatibility guarantees. Moving this slow is why the implementation is much better than the same in C#, Kotlin, or JS.
- dang 6y agoI hope those links didn't seem like criticism in any way! I just post them because readers like to look at past threads.
- nahuel0x 6y agoHow Loom manages killing a vthread from another vthread? In Erlang you can do it safely and without needing to check a cancellation signal in the process to be killed. Also, Erlang has per-process heaps, an usually overlooked feature that gives soft-realtime capabilities, avoiding GC hiccups. JVM+Loom seems to be closer to Go than Erlang.
- aidenn0 6y agoDoes that mean message-passing in Erlang necessarily includes copying?
- toast0 6y agoI'm not qualified to say it copying is necessary at a language level, but in terms of implementation, BEAM always copies for message passing, AFAIK. A small caveat is that Erlang has a Refc binary type that is reference counted, when sending a message with a refc binary to another process on the same node the content isn't copied, just the reference value (like a pointer) and the reference count is incremented. There is an area where copies could potentially be avoided, but I don't think they are. Recent versions of beam have an optional off-heap message queue feature; some software patterns have a proxy process that accepts messages and sends them as-is to another process; if the message is off-heap for the proxy process, and it would send to the next process off-heap, it could be possible to avoid copying it, but it might be a bit tricky. (I don't think this is done, but that's why I said AFAIK earlier)
- thu2111 6y agoJVM has pauseless GCs now, in fact two of them! The Erlang multi-heap approach is much less compelling now GC pauses are finally vanquished as a problem.
- The_rationalist 6y agoAre there still legitimate use cases of using real threads vs virtual threads?
- aidenn0 6y agoDoes Loom make JNI unusable [edit] C-f JNI is my friend. They pin a fibre to an OS thread for the dynamic extent of a JNI call.
- klysm 6y agoI'm really excited to see how this impacts the performance of akka and other stream-like things in the JVM ecosystem. I've spent far too much time tinkering with thread pools and digging through profiles with Unsafe.park everywhere.
- haspok 6y agoWhy is there still no timeline? I don't see any previews, let alone GA features in JDK15, which means that by JDK17 probably nothing's going to be released. Which is sad, because that pushes the GA to the next LTS a extra few years down the line... (2023/2024 the earliest) :(
- BenoitP 6y ago> I don't see any previews There is an early access [1] ---- As for having in in JDK17, Ron provides an answer in the reddit thread [2] [1] http://jdk.java.net/loom/ http://jdk.java.net/loom/ [2] https://old.reddit.com/r/programming/comments/gkgzld/state_of_project_loom_on_jvm/fqulhig/ https://old.reddit.com/r/programming/comments/gkgzld/state_o...