language-based async I think generally hurts lower-level languages when used or best it is ignored. The two I look to for this are rust and c++.
async (such as the coroutine/user threads c++ and rust went for) hurts latency straight out. Latency is far less forgiving and more difficult to code for than throughput: you can’t scale your way to success. And io_ring doesn’t save you (it doesn’t even help and has worse latency than epoll).
For throughput it is good enough to allow yourself to scale yourself to a, and it provides an ecosystem for those that aren’t the best network programmers to work in.
However, that comes with a price, as rust has learned. When async was being done there were post upon post about how it will fracture the rust network ecosystem, and after it left nightly and moved into the current release branch, there were people who even worked on it talking about how it will destroy rust.
and they’ve been right. you cannot pick up a rust network library that doesn’t use async now. It sucks all the network code into it. Even libraries that have a synchronous interface just use async and then wait so would be a very slim simple network turns into another tokio nightmare. There no longer such a thing as simple rust network code.
Async, the eater of code, dominates the entire stack now, and isn’t very flexibly when trying to finely tune network code or do things that is didn’t invisions (i remeber trying to up the recv buffer sizes in an async app was just the absolute mess (you might up it in tokio, but your http lib had to support it, and also you tls lib, and you websocket lib, etc… async model of the network stack doesn’t fit well with the model you get in userland). Other failed idea: setting certain options on the accept socket that needed to be set before the accept (this is point where i gave up and started looking for other languages after a few years of rust).
You wind up with a lot of mediocre libraries with no real way to make the real winners. Great if that is your language goal (Go) or the languages value add exists in another area (JS), bad if you are trying to be a high performance system language where people write their own tcp stacks (c++).
C++ has library level async and coroutines, but nobody uses them. yo need to have really high performance requirements to put the effort into them, but not so high that you are pushing the limits of async, so the band that justifies use is rather thin.
i hope it never comes back to the language. Adding to the issue that io_ring isn’t the best for low-latency message passing (its strenght is in high throughput streaming data), but everybody implements that, forgets about the low-latency crown (or just tells them its good enough, which it never is), all the network libs get sucked into the async hole, and the ones that don’t start to form an alternative stack that is incompatible with async and the network space is split.