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

"Want to use an async library? There’s a chance you can’t use it outside of a specific async runtime."

I complained about this here[1]. I'm told "Tokio won, it's not a problem anymore." Wrong. It's still a problem and it's a killer.

[1] https://news.ycombinator.com/item?id=37892655



Can you help understand why somebody wouldn't use Tokio/why it didn't "win"?


Tokio isn't the fastest conceivable runtime. Tokio isn't the smallest conceivable runtime. Tokio isn't the simpilist conceivable runtime. Tokio does not port to all conceivable environments. Tokio isn't the async-std runtime.

And so, for some or all of these reasons, right or wrong, various Rust libraries wed themselves to runtimes other than Tokio.

You can thunk around these things, but it's miserable, yielding subtle, inscrutable code that you will not understand in six months when you have to maintain it. And the real fun begins when you need to handle Err, and all the abstraction leaks around Send and threads ruin your day; more thunking, Boxing errors (omfg) and even subtler and more inscrutable code.


Is this to say async-std is faster + smaller + simpler + more portable than Tokio?


I think what they were trying to say is that Tokio ended up being a general purpose async runtime so naturally it can't be the most optimal solution for every case. But because various libraries kind of force you into Tokio, it's very hard to use a runtime that's optimal for your specific problem. You'd have to give up on a lot of convenient libraries out there.


Yeah those are terrible responses.

Tokio monoculture is a serious problem.


On the supposed "monoculture":

First, I have to wonder whether any of this can be legitimately elevated to the level of a "culture." Right now, according to GitHub "insights," tokio-rs has approximately 2.0 regular, every day contributors. And that's the most widely used Rust async runtime. Everything else is likely even more thin.

Second, Tokio has a lot of share because it was early and aggressive in actually delivering usable async documentation and code. I recall, years ago, reading Tokio documentation on how futures worked and grasping these concepts all the way from file descriptors one might epoll() in C, up to the Rust abstractions, and thinking "hell, I could write an executor from first principles based on this." Tokio earned the advocates it has, as oblivious to the real state of things as some of them might be.

I think the real problem is that async Rust is incomplete. As I said elsewhere, async Rust syntax is fine. The implications of async Rust exposed some papercuts in the language that have had to be dealt with since, but the core syntax is fine. I believe that can be attributed to the serious minded attention that the syntax received from people way, waaay up the cognition curve. The part that didn't get enough thought was async runtimes. In an ideal world, one would develop a Rust library that utilizes and/or implements asynchronous calls and transparently, flawlessly run on any correctly implemented runtime alongside any other number of libraries also utilizing and/or implementing async calls.

That is not the case, and the damage that's doing is severe. For every one person, such as myself, that will dare attempt to articulate this pain and, in the process, certainly revealing clear evidence of blatant ignorance, a thousand others just silently gave up.


Yes I think we agree, though I'd quibble about the async syntax; I use it but I have philosophical concerns about it. But I do think tokio is on the whole well implemented. But it is not a good thing for a single runtime to dominate the language like that.

I've at least thought-experimented with what it would take to write my own code agnostic enough that it could run on both e.g. tokio and e.g. monoio etc. and, well, it just can't happen. Even if you find neutral/unbundled implementations of locks, channels, utilities, to depend on instead, you end up stuck at: task spawning, and any kind of I/O. The former, to me, is a glaring absence from the language standard; async should not have gone out the door without support for it.


I can't argue too much on your view of the syntax. I employ the weasel word "fine" because my experience with it is that I have little to no trouble understanding and using async Rust syntax: I can read and write async Rust and conceptually grasp what is likely going on in the runtime. I have to allow that perhaps it isn't sufficient, and maybe even that this is a factor in the runtime problem.

But there are other, non-syntax issues, such as synchronization primitives, IO events, etc. that are clearly underspecified. No maybes about it.




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

Search: