>All processes running on Lunatic are preemptively scheduled and executed by a work stealing async executor. This gives you the freedom to write simple blocking code, but the runtime is going to make sure it actually never blocks a thread if waiting on I/O.
I'm reading/writing a fair amount of Python and C# at the moment, and the more I see async/await in use, the less I'm convinced by it as a language feature. Whilst the guidance seems reasonable on reading (e.g. [0]), the reality is that it increasingly becomes the norm to find code where most functions/methods are declared as async, and most implementations are littered with await.
So Lunatic's approach resonates. There again, as an Erlang fan, I'm pre-disposed to that concurrency model. So definitely not unbiased.
I was working on a thesis about how async by default was at least as much trouble as it's worth, but at the end I realized that to a first order approximation, my 'solution' was essentially asking for a return to Promises. We all know the problems with that architecture, and I have a mountain of my own anecdotes there, so if I can only come up with alternatives that even I hate, I'm mostly keeping my opinions to myself.
> This does not use async/await "colored" functions:
Thanks, yes, that's my point. I'm not convinced by async/await as a technique. I'm finding the "non-blocking fibers" approach much preferable in practice.
They both have their own place. If you're writing code where you care about thread identity, like a GUI code or using a native thread for various reasons and you want specific control, async/await gives you that control. If you don't care about thread identity and just care about pure throughput, pre-emptive is less cognitive load up until the work stealing starts to matter.
C#'s async is cooperative multithreading and this is pre-emptive multithreading. Both have different goals and they have their own place.
My expectation is if/when Java's Loom tech gains steam Microsoft will release its own pre-emptive thread pool into C# alongside async/await (again because they're different styles with different goals). Then everyone will be happy, ...right?
>C#'s async is cooperative multithreading and this is pre-emptive multithreading. Both have different goals and they have their own place.
Yes, but that's not really the issue at hand. The issue is that async/await, as a particular _implementation_ of cooperative multi-tasking, has resulted in code bases dominated by async function declarations and bodies filled with awaits. Where, qualitatively, the volume of async/await code outweighs the actual need for concurrent/non-blocking execution.
>My expectation is if/when Java's Loom tech gains steam Microsoft will release its own pre-emptive thread pool into C# alongside async/await (again because they're different styles with different goals). Then everyone will be happy, ...right?
Maybe. That'll depend on whether they can address the viral nature of async. And it won't automatically get rid of the `xxxMethod/xxxMethodAsync` duality that has arisen. It'll also add yet more cognitive overload for developers ("should I use cooperative or pre-emptive multi-tasking here?").
Personally I think the whole coloring controversy is overblown. Complaining about it is strange to me. The awaits must be there because that's what makes it cooperative and explicit not implicit and abstracted. It's like complaining about explicit memory management for garbage collection. GC is great but GC can't do things you can do explicitly. And unlike memory management, async/await is safe, just mildly verbose.
Async/await is probably the best at what it does well. You simply can't do the things that involve native thread management (among others) with implicitly scheduled green threads without locks or some other worse paradigm.
From my own experience in the Elixir community watching libraries develop the non-blocking preemptive actor-model concurrency is a good default for most situations. Dropping into things like Rust NIFs has been great for those hands on situations where direct memory control is needed - but more often than not its the exception not the rule.
I'm reading/writing a fair amount of Python and C# at the moment, and the more I see async/await in use, the less I'm convinced by it as a language feature. Whilst the guidance seems reasonable on reading (e.g. [0]), the reality is that it increasingly becomes the norm to find code where most functions/methods are declared as async, and most implementations are littered with await.
So Lunatic's approach resonates. There again, as an Erlang fan, I'm pre-disposed to that concurrency model. So definitely not unbiased.
[0]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...