Live data from Hacker News

A four year plan for async Rust

without.boats

151–160 of 236 posts

Re: A four year plan for async Rust

#151

Earlier quoted context omitted.

to be honest, HN is one of the few venues where I think someone who is core to a project might actually see what is said about a language. I've tried getting involved in mailing lists and stuff, but they aren't often as welcoming to this discussion as one might assume. My hope is that by raising these things on HN, someone will take notice in a different way and at least start considering / revisiting alternatives

All of this would be correct in an alternative reality where everybody in the Rust community, including every person ever involved in the language's evolvement isn't aware of these complaints.

Your comment is self defeating. The reason people are aware of these complaints is because they keep being brought up, over and over.

This is a serious wart on language design and while I can agree that it's likely too late to fix it for Rust, there is a kind of race among new languages to be a successor to C++ in many of the domains C++ is used in, and while I think Rust does hold a lead in that race, the race is not over.

A language that can provide an ergonomic solution to concurrency would absolutely provide a huge boost to any such language, and so to people in that space, listen to these complaints. Async/await is not a good solution to this problem.

You almost always hear people complaining about async/await in every language it's a part of but you rarely hear people complain about how Go manages concurrency.

Re: A four year plan for async Rust

#152

TBH I think that, for the most part, I will only benefit from a few of these - mostly in terms of sugar. I routinely have positive experiences with Async rust and basically never have negative experiences/ issues that crop up because of it. In 3 years of writing Rust full time I had one async problem one time - I accidentally was causing an infinite select! loop in a tonic server, so the server would hang. Not really…

Is that the same as the "Unforgetable types" mentioned in the blog?

I never thought about it but, my only problem with C's manual destructors is that the compiler doesn't check that you remember to call them. If we accept a language like Rust that does sophisticated static analysis, it doesn't need to delete things for you, it only needs to be sure you have a plan to delete everything.

That's interesting.

Re: A four year plan for async Rust

#153

> AsyncIterator and async generators For what it's worth, Dart has had synchronous and asynchronous generators (including `await for` statements) for as long as its had async/await. They are neat features. I've definitely written code using synchronous generators that would be hard to manually transform into a custom Iterable implementation. But they add a large amount of complexity to the language implementations an…

I do wish discussions like the linked blog were more clear on specific use cases features would enable. Async summation shows off the syntax sure, but I don’t know any real world problems that are currently hard that this would make easy. Not to say there aren’t, just I don’t know them and would love to understand!

Re: A four year plan for async Rust

#154
post #140

Earlier quoted context omitted.

Yes this works too. People complaining about async being contaminant are often so much prejudiced against it that that haven't even tried to understand the basics.

Having written an async library (as in, the non-blocking stuff and state, that to the caller looks like async)... Understanding it isn't the easiest.

Yeah writing the underlying machinery is definitely much more complicated! Most users of async libraries don't need to worry about this though

Re: A four year plan for async Rust

#155

> AsyncIterator and async generators For what it's worth, Dart has had synchronous and asynchronous generators (including `await for` statements) for as long as its had async/await. They are neat features. I've definitely written code using synchronous generators that would be hard to manually transform into a custom Iterable implementation. But they add a large amount of complexity to the language implementations an…

I'm not sure "percentage of usage" is a metric you can use to fully decide how "useful" something is. Take macros in Clojure for example, usually you just have a few of those, but the ones you have are really useful, they give a lot of functionality and practicality to the language. Maybe the same thing is happening with sync/async generators?

That's a good observation about a lot of language features, yes. Macros are a particularly good example.

But for a feature like generators which is, I think, essentially user-facing syntactic sugar, I do think a count of usages is a pretty good measure of usefulness.

It's probably also worth noting that my data here is from published packages, which tends to skew towards reusable libraries and away from application code. So, if anything, I would expect this to be an over-count of their use if they primarily made libraries/frameworks useful on behalf of application developers.

Re: A four year plan for async Rust

#156

TBH I think that, for the most part, I will only benefit from a few of these - mostly in terms of sugar. I routinely have positive experiences with Async rust and basically never have negative experiences/ issues that crop up because of it. In 3 years of writing Rust full time I had one async problem one time - I accidentally was causing an infinite select! loop in a tonic server, so the server would hang. Not really…

Is that the same as the "Unforgetable types" mentioned in the blog? I never thought about it but, my only problem with C's manual destructors is that the compiler doesn't check that you remember to call them. If we accept a language like Rust that does sophisticated static analysis, it doesn't need to delete things for you, it only needs to be sure you have a plan to delete everything. That's interesting.

> Is that the same as the "Unforgetable types" mentioned in the blog?

Pretty much, yes.

> I never thought about it but, my only problem with C's manual destructors is that the compiler doesn't check that you remember to call them.

Right, so in this case the compiler would force you to consume the value somehow. This is "linear" typing.

Re: A four year plan for async Rust

#157

Earlier quoted context omitted.

I agree, there's questions that need to be answered, and I don't know that I even have answers to give to them. I will say, that its clear, to me and a good portion of Rust users, that async in Rust needs DX improvements. Its one of the top features of the language that is used alot and people struggle with often[0] [0]: To be fair, async in any language trips up developers pretty often, though I think Rust can give…

> I don't know that I even have answers to give to them. To be honest, this is why this discussion always gets frustrating: people demand change that is impossible, and then when pushed for how to accomplish the impossible, they throw up their hands. I do not think you or anyone else is doing it maliciously, but for some reason, on this specific topic, it happens endlessly.

My best shot at this is something akin to a runtime built-in to the stdlib that can be opted out, similar to how you can build something with `no-std` so there is no reliance on `libstd`. Perhaps this is a great place where you drop into more "raw" async programming using the async / await primitives. You lose DX sugar but slim out the runtime for embedded work.

Ideally, the runtime could handle anything written using lower level primitives as to not completely kneecap libraries that need to work with `no-async-runtime` (or whatever you want to call it).

This would at least alleviate a common concern I hear around this, which is runtime bloat.

That seems like a step in the right direction to integrate a unified async runtime with an alternative / better syntax[0]

[0]: I want to note, that C# is the only language I ever worked in that supported async in two constructs. There is the traditional async / await, which is by far the most common. Before that though, there was event driven async programming (with support for background workers and other async features) and that is also still supported, and they can interop with each other (with some caveats)

Re: A four year plan for async Rust

#158

Async is a huge wart and I try and avoid it wherever possible. It's simply not useful in a lot of cases that I encounter. However, if a library uses async, you have little choice but to make your whole project async. This adds to its horrible reputation.

What Rust libraries use async that you think should not? I can think of one, but otherwise every library I've encountered uses async because its intended for the kind of networking service that benefits from using non-blocking IO.

Example from the recent past: I wanted a quick Rust code to stream s3 object, uncompress with zstd and untar the content to a directory. aws-sdk-s3 supports only async (tokio), tar crate only blocking, async-tar only async-std, async-compression only tokio. Hard to paper over it with `block_on` because of the streaming part. I don't remember what I actually did, but it doesn't matter - having to come up with a magic working combination is exactly the pain.

I just wish everything would at least still support blocking IO as a common denominator, so there's at least a baseline that is known to be possible. 99% of percent of the time I do not need benefits of async, because I write small software for relatively small, but still real use-cases. And using Rust ecosystem was easier just a few years ago than it is now for these use-cases, as blocking Rust was not yet relegated to be a second class citizen, replaced by an immature and fractured async.

Re: A four year plan for async Rust

#159
post #75

Earlier quoted context omitted.

Needing a helper library for something as simple as async so you don't go mental is really not good enough. I see the same thing with error handling - every Rust project I see imports a helper because it's too clunky otherwise.

If you don't want to pull in a helper library to run async code in a sync context, then why pull in an async library at all? Rust is not a batteries-included language like Python. There are lots of libraries that are very commonly used in most projects (serde, thiserror, and itertools are in almost all of mine), but this is a conscious choice. They say in Python that the stdlib is where projects go to die. I'd rather…

The problem is that a large number of popular libraries has converted to async, 95+% of them to Tokio.

So you are stuck with smaller, less battle tested products if you'd rather not pull in 100+ crates of dependencies that are doing nothing but inflating the build times and file sizes (for your particular usecase).

Example: reqwest vs ureq

Re: A four year plan for async Rust

#160

Earlier quoted context omitted.

> I don't know that I even have answers to give to them. To be honest, this is why this discussion always gets frustrating: people demand change that is impossible, and then when pushed for how to accomplish the impossible, they throw up their hands. I do not think you or anyone else is doing it maliciously, but for some reason, on this specific topic, it happens endlessly.

My best shot at this is something akin to a runtime built-in to the stdlib that can be opted out, similar to how you can build something with `no-std` so there is no reliance on `libstd`. Perhaps this is a great place where you drop into more "raw" async programming using the async / await primitives. You lose DX sugar but slim out the runtime for embedded work. Ideally, the runtime could handle anything written usin…

The only thing this would change is not needing to "cargo add smol" which already exists as a smaller runtime if you need it. That wouldn't solve the fact that a large part of the ecosystem would still need the features of Tokio, and would still use them. So you still have interoperability problems, until figuring out how to make runtimes swappable, and that is open-ended work. (and also assumes that smol's particular choices are correct for this, and that everyone maintaining the stdlib agrees that they are, and that the folks on the libs team are willing to step up and start maintaining an entire async runtime, etc etc etc)
Post reply on HN