Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I still prefer Go, for its first-class lightweight threads. They make _everything_ so much better to debug, compared to async/await that is available in C# and Kotlin.

That being said, Java has recently released Project Loom, but it's poorly integrated and often causes subtle issues. It'll require a couple more years to mature.

C# doesn't have anything like this for now.



Go is worse at _lightweight_ concurrency because each Goroutine is much costlier than each .NET task. Also Go has less pleasant concurrency semantics comparatively speaking because Goroutines cannot yield a value - you have to spawn a channel on top of spawning a Goroutine or you need to use a wait group or similar. .NET offers better experience for concurrency-centric code at a much lower overhead for code that has light of finely grained concurrent operations.

https://hez2010.github.io/async-runtimes-benchmarks-2024/tak...


A million tasks results in 2.5G memory spent (for stacks).

This overhead is indeed real, but it is basically immaterial. If you're using that many goroutines, you are going to be CPU-bound unless it's a very special type of workload like a WebSocket dispatcher.

In return, you get _normal_ stack traces, and a normal debugging experience. Not a callback hell of async/await. Also no "colored functions" nonsense.

Coroutines make sense only for something small and trivial, like the classic tree iterator. And Go now has that: https://go.dev/blog/range-functions


> In return, you get _normal_ stack traces, and a normal debugging experience.

Whatever language you have in mind, it isn't C#. Because all those work perfectly fine there. Please also do a cursory read of what coroutines (stackful vs stackless) in the context of concurrency are. And in Go, all functions are colored, often in ambiguous way due to poor culture of not passing the context where it matters, and goroutines panicking in dependencies that cause uncatchable application crashes. Never change, Go community.


IIRC C# investigated virtual/green threads, but decided to drop it because of poor interactions with reentrant code from async/await. The fact that C# went all in on async/await when it was the rage has prevented it from adopting a better solution. Java's conservative attitude fares better for such fundamental changes.


There is reason async/await got so popular after it was adopted by C# based in the early Async work in F# :)

Stackful coroutines have their pros but they are not a better choice. Rust did not and will not adopt them nor any other serious systems programming language will.

You don’t have to follow noisy style you often see - tasks compose nicely and express deferred operations incredibly well in a way that will not blow up on you in a surprising way.

There is an ongoing Async2 project which will massively reduce task state machine overhead further by only ever paying for it in the code that actually suspends rather than the code that just forwards the calls or doesn’t. It will likely land as preview in .NET 10 and as full release in .NET 11.


I only know C#'s async/await, and know nothing about goroutines / virtual or green threads.

You seem knowledgeable on the matter, care to share some resources that might help me grok the differences?


> Stackful coroutines have their pros but they are not a better choice.

Hard disagree. Coroutines are absolutely useless for anything non-trivial, as debugging them becomes a total hell. They are still a callback hell, just with a lot of sugary goo slathered on it.

Coroutines also result in the "colored function" problem, that is fundamental for them.

Meanwhile, Go lightweight threads just work. Debugging is simple, and you don't have to think about spooky actions at a distance from event loops that dispatch coroutines.


Please re-read my reply. Goroutines are stackful coroutines.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: