Live data from Hacker News

Why asynchronous Rust doesn't work

theta.eu.org

161–170 of 499 posts

Re: Why asynchronous Rust doesn't work

#161
post #144

Earlier quoted context omitted.

>Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. Believe me, I do understand the motivation behind the decision to push async stabilization in the developed form (at least I think I do). And I do not intend to argue in a bad faith. My point is that in my opinion the Rust team has chosen to get the mid-term boost of Rust popularity at the expense of t…

Does anything about the implementation of async prevent a future completion-based async feature? Say it's called bsync/bwait.

Yes, it's possible, but it will be a second way of doing async, which will split the ecosystem even further. So without a REALLY good motivation it simply will not happen. Unfortunately, the poll-based solution is "good enough"... I guess, some may say that "perfect is the enemy of good" applies here, but I disagree.

Re: Why asynchronous Rust doesn't work

#162
What’s wrong with async_std? The author calls it spicy. I’ve been using Surf and Tide which are built atop it and things have been a breeze. It is essentially a standard lib where all functions are red (a solution as I’d interpret things based on the linked rant). In my experience rust async’s only wart is the incredibly confusing function signatures you get with Box<Pin<... which I would think can be cleaned up.

Re: Why asynchronous Rust doesn't work

#163
post #100

Earlier quoted context omitted.

> The problem is that Rust async was rushed without careful deliberation As someone who observed the process, this couldn't be further from the truth. Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. > Without introducing Rust 2? Highly unlikely. This is incorrect. async/await is a leaf node on the feature tree; it is supported by other language featu…

>Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. Believe me, I do understand the motivation behind the decision to push async stabilization in the developed form (at least I think I do). And I do not intend to argue in a bad faith. My point is that in my opinion the Rust team has chosen to get the mid-term boost of Rust popularity at the expense of t…

I and many others would disagree that they made the decision "at the expense of the long-term Rust health". You aren't arguing in good faith if you put words in their mouth. There is no data to suggest the long-term health of rust is at stake because of the years long path they took in stabilizing async today. There are merits to both models but nothing is as clear-cut as you make it to be - completion-based futures are not definitively better than poll-based and would have a lot of trade-offs. To phrase this as "Completion based is totally better and the only reason it wasn't done was because it would take too long and Rust needed popularity soon" is ridiculous

Re: Why asynchronous Rust doesn't work

#164
post #137

Again, feeling old, I'm not seeing a lot wrong with threads. A thread pool, if you insist, but explicit workflows as opposed to chaining together callbacks and contexts ... just seems really easy.

I think you're spot on. For 99% of the use cases, traditional threads are the way to go. It's only when you have a truly massive number of logical threads (>100k, or even >1M) not doing anything most of the time, that OS threads reach their limits due to their aggregate stack size. In other words: web services, where each server thread either waits for input from the client or for a database reply, and only if they h…

You're right but even most big players can probably just use threads. If you are serving 1 million clients per VM you are probably taxed for other resources besides threads unless 99.99% of your clients are guaranteed to idle.

Re: Why asynchronous Rust doesn't work

#165
post #86

The big issue is that non-GC concurrency is still effectively a CS research topic. In a GC language, you can "just" let the GC system clean up after you're done--who owns allocation and cleanup isn't an issue. In a non-GC language, who allocates and cleans up what and who pays for that suddenly becomes a fundamental part of the domain. For example, I have seen a zillion "lock-free" data structure libraries in Rust, a…

I'd like to understand what you mean by this. I'm no expert on Rust lock-free designs, but what are the "amortization guarantees" that you refer to? Is there something that I can read that explains this in greater detail?

Basically any background about java.util.concurrent (the development mailing list is archived, IIRC). Also, anything by Cliff Click and Azul. Okasaki talks about it in the context of functional data structures rather than concurrent: https://en.wikipedia.org/wiki/Purely_functional_data_structu...

But, let's talk about something like CopyOnWriteArrayList.

If I add() a CopyOnWriteArrayList(), a copy of the underlying data comes into existence with the new element. That should certainly get charged to the thread doing the add(). Fine.

Some Iterators are probably still pointing at the old underlying data. Not a big deal.

So, the final Iterator() with references to old data finally finishes and gets deallocated/dropped.

Now, all the underlying data that got copied is no longer relevant and needs to be deallocated/dropped.

So, who does that?

Does that happen on a thread that next calls get()? If so, get() is now O(n) worst case. That certainly doesn't make people happy.

Does that happen on a thread that next calls add()? Well, we can have a lot of iterators that were all working and now ended. So, that add() might be deallocating a LOT of copied stuff. This might be where it has to be done, but the fact that your O() performance is dependent upon the size of the data and the number of copies that got made makes you O(n^2)-ish (O(n*k) to be more precise). That's not good.

Does the deallocate happen on thread where the last Iterator() got dropped? Having to deallocate the universe because you just happened to be the last one using the underlying data store doesn't seem like a good idea.

Perhaps you do a little bit of deallocation work on every get()? Probably good for throughput, but it sure makes the data structure a lot more complicated.

Perhaps you have an explicit deallocation call. That kind of defeats the whole point of using a language like Rust.

In a GC language, this all gets charged to the GC thread and swept under the carpet. That's what I'm thinking about when I say "amortized".

There's also a slightly different amortized. In C++, for example, when you insert() into an unordered_map(), the "normal" time is O(1), but every now and then you get an O(n) while the structure reallocates. This results in an "average/amortized" cost of O(1) if the reallocation is done intelligently (generally doubling in size every overflow).

Re: Why asynchronous Rust doesn't work

#166

> Was spinning up a bunch of OS threads not an acceptable solution for the majority of situations? It's worth remembering that this is still a very acceptable thing to do in some cases. And spawning OS threads is sometimes easier to write and easier to read, and easier to reason about than async code. Just because async is in the language, don't feel like you need to use it everywhere.

> Just because async is in the language, don't feel like you need to use it everywhere. Except that you will have to because no alternative library exist

It's easy to convert an async function into a blocking one. For example, you could use https://docs.rs/async-std/1.9.0/async_std/task/fn.block_on.h...

So just use the async functions from the library synchronously if you want.

Re: Why asynchronous Rust doesn't work

#167

A bigger problem in my opinion is that Rust has chosen to follow the poll-based model (you can say that it was effectively designed around epoll), while the completion-based one (e.g. io-uring and IOCP) with high probability will be the way of doing async in future (especially in the light of Spectre and Meltdown). Instead of carefully weighing advantages and disadvantages of both models, the decision was effectively…

Why did polling have to be baked into the language? Seems bizarre for a supposedly portable language to assume the functionality of an OS feature which could change in the future.

Meanwhile C and C++ can easily adopt any async system call style because it made no assumptions in the standards about how that would be done.

Rust also didn't solve the colored functions problem. Most people think that's an impossible problem to solve without a VM/runtime (like Java Loom), but people also thought garbage collection was impossible in a systems language until Rust solved it. It could have been a great opportunity for them.

Re: Why asynchronous Rust doesn't work

#168
post #136

Earlier quoted context omitted.

You can't arbitrarily compose 2 functions with mismatched types. So i don't think this argument holds in a typed language.

The problems are (1) either you write two versions of almost every function or you can only support one use case (sync or async). If you could write generic functions which work in both cases it would be better. (2) it creates a lot of noise writing async/await. It's like if we had to always write x = call f() in the sync case.

If you write your functions as async, it's trivial to make a sync wrapper out of it.

Re: Why asynchronous Rust doesn't work

#169
post #163

Earlier quoted context omitted.

>Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. Believe me, I do understand the motivation behind the decision to push async stabilization in the developed form (at least I think I do). And I do not intend to argue in a bad faith. My point is that in my opinion the Rust team has chosen to get the mid-term boost of Rust popularity at the expense of t…

I and many others would disagree that they made the decision "at the expense of the long-term Rust health". You aren't arguing in good faith if you put words in their mouth. There is no data to suggest the long-term health of rust is at stake because of the years long path they took in stabilizing async today. There are merits to both models but nothing is as clear-cut as you make it to be - completion-based futures…

I do not put words in their mouth or have you missed the "in my opinion" part?

The issues with Pin, problems around noalias, inability to design a proper async Drop solution, not a great compatibility with io-uring and IOCP. In my eyes they are indicators that Rust health in the async field has suffered.

>Completion based is totally better and the only reason it wasn't done was because it would take too long and Rust needed popularity soon

And who now puts words into other's mounts? Please see this comment: https://news.ycombinator.com/item?id=26407565

Re: Why asynchronous Rust doesn't work

#170
post #26

I don't think any of this is actually a reason why async rust doesn't work. The function color problem is a bit overblown, it hasn't broken nodejs yet either. Most code is sync, sync can call async and vice versa, and the ecosystem hasn't come tumbling down yet (since most Rust isn't whichever async application runtime for web apps is currently in vogue - its a systems language after all). Either way there are bigger…

> The function color problem is a bit overblown, it hasn't broken nodejs yet either.

I agree; and I would also point at C#, which is the originator of the async/await syntax, and has had it for over 8 years now, with the ecosystem embracing it for most of that period. It works.

Post reply on HN