4 ms·
> I wonder if the advent of async/await in all the popular and upcoming programming languages will be seen, after some (buffering) interval, as a disaster of ma
by lazulicurio 7y ago
> I wonder if the advent of async/await in all the popular and upcoming programming languages will be seen, after some (buffering) interval, as a disaster of major proportions. And, I wonder how the programming world will respond to the disaster.
I think that there is value in async/await as a concept, but that some language's specific implementations will be eventually seen as a mistake. My primary experience is in .Net, and I've grown disenchanted with async/await in that realm. I feel like it makes the easy things easier and the hard things harder[1], which, IMO, is the wrong trade-off for a concurrency primitive[2]. By comparison, what I've read about async/await in Rust seems very promising.
[1] Specifically, I think that the Task API is warty and over-complicated, with abominations such as .ConfigureAwait (I know that there are situations where it can be useful, but those don't make the method any less terrible). While await doesn't strictly depend on Task[1a], in practice you're going to be using Task.
[1a] http://blog.i3arnon.com/2018/01/02/task-enumerable-awaiter/ http://blog.i3arnon.com/2018/01/02/task-enumerable-awaiter/
[2] Before anyone chimes in with "async/await has nothing to do with concurrency/threads---it's just state machines": yes, that is technically true in the narrow sense of how the compiler desugars the async/await keywords. However, as soon as you start talking about actually scheduling and executing your tasks, concurrency/threads become very important.
- sk5t 7y agoI actually liked .NET async/await because it came with good usable libraries for async RDBMS operations tied into NT IO completion ports, easing a super common bottleneck; compare to other common RDBMS clients that might offer a facade of asynchrony but are really just blocking and queuing behind the curtain. The task library (TPL) is a smidgen wordy, as was MSFT's way about ten years back, most folks will never get deep into it though.
- LennyWhiteJr 7y agoasync/await in .NET is actually good because they added async equivalent APIs to nearly all blocking operations. There's also always (from what I've seen) an optional cancellation token parameter that allows an easy mechanism to alleviate backpressure. Need an easy way to cancel 100 async requests? Easy, just pass in a cancellation token and cancel it when needed. All the requests will throw an OperationCanceledException which can be cleanly handled. I haven't seen anything this nice in javascript or python.
- lazulicurio 7y ago> async/await in .NET is actually good because they added async equivalent APIs to nearly all blocking operations I mean... I get it---it's great how Microsoft put in an effort to add async equivalents to most of your standard operations. But my complaint is about how almost all of those async methods are built upon Task/Task<T> (which, IMO, is a flawed foundation). > There's also always (from what I've seen) an optional cancellation token parameter that allows an easy mechanism to alleviate backpressure. > Need an easy way to cancel 100 async requests? Easy, just pass in a cancellation token and cancel it when needed. All the requests will throw an OperationCanceledException which can be cleanly handled. No significant disagreement from me there. It is nice that most core async methods support (or try to support) cancellation.
- cies 7y ago> But my complaint is about how almost all of those async methods are built upon Task/Task<T> (which, IMO, is a flawed foundation). Do you know any not-flawed implementation?
- lazulicurio 7y agoImplementations as in .Net implementations? Or implementations as in other languages' implementations? As far as .Net goes, I've not looked around. I feel like it would be somewhat of a fool's errand to develop an alternative async/await implementation because almost all of the core APIs use Task/Task<T>, so you'd either be using Task/Task<T> anyway or re-producing a lot of APIs.
- WorldMaker 7y agoasync/await itself is "subtly duck typed" in most of the .NET compilers along with other bits of compiler work (among other examples IEnumerable/IEnumerable<T> in C#'s foreach is also subtly duck typed and not dependent on the specific BCL interfaces, though almost no one would use bespoke interfaces), which is how .NET Core was relatively easily able to add ValueTask/ValueTask<T> and a lot of .NET Core APIs have been slowly migrating to ValueTask/ValueTask<T> without much compatibility breaking trouble.
- Animats 7y agoThreads are state machines. Packaging up task state as a closure and packaging up task state as a stack do roughly the same thing. In Go, the two are closer together than in other languages where async was a retrofit.
- lazulicurio 7y agoSure, but if you're going to go that route, why not just say "the entire computing system at a whole is just a state machine, so what's the difference"? Threads provide a very privileged form of state machine that are tightly coupled with the underlying platform. This means you have to be thinking about things like cache coherency and context switches. Without careful use of other synchronization primitives (or stronger language guarantees[1]) it's easy to find yourself writing incorrect or less-than-performant[2] code. [1] Like in Rust [2] e.g. creating bottlenecks by blocking on access to a shared resource (Edit: perhaps a better way to word that would be "accidentally reintroducing blocking behavior by using synchronization primitives to access a resource")