4 ms·
> 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
by 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?
- Skinney 6y agoGolang only has one colour. `funcA` works the same way in sync (`funcA()`) or async (`go funcA()`) context.
- aliceryhl 6y agoGolang doesn't really have a sync context. It has one color because everything is async. The `go` operation is not comparable to `await`, rather it is comparable to spawning.
- Skinney 6y agoThere’s a difference between sync and async code in Go, which is why you have all the normal threading primitives like mutexes, semaphores and blocking queues/channels. The point is that functions themselves don’t come in sync or async flavors. Just like in Java.
- aliceryhl 6y agoI don't think the existence of mutexes, semaphores and queues/channels imply that there is a sync version of Go. You can totally use those primitives in asynchronous Rust too. You call the queues blocking, but they aren't really in the sense of "blocking" usually used when talking about async in Rust. The Go runtime can and will preempt your Go code in the middle of waiting for a channel to run some other task, and this preemption is what makes it different from a blocking Rust channel. An async Rust channel will also make the calling function wait for messages when you await the receive method. Basically my point is that because any Go code can be preempted at any point, that makes all Go code async. The language not making you type await on everything doesn't make it sync.
- int_19h 6y agoGreen threads have been around for a very long time before Go, and there's nothing specific about Go that made them solve any problem they didn't solve before. It just so happens that this is a solution that comes with many downsides, which is why it's not universally adopted. Indeed, Java itself had green threads (only!) in the first couple of versions.
- pron 6y agoIts downsides depend on the language. It works better in languages with GC than languages without, and it works better in languages that rarely rely on FFI than in languages that rely on it a lot. One of its major "downsides" is that it's just harder to implement than async/await, and requires control over the backend, something few languages have (even Rust is on top of LLVM). For example, Koltin just couldn't implement useful usermode threads because it has no control over the JDK.
- 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.