Live data from Hacker News

Async Rust never left the MVP state

tweedegolf.nl

231–240 of 273 posts

Re: Async Rust never left the MVP state

#231

Earlier quoted context omitted.

> Retrospectively, i think everyone is satisfied with the adopted syntax. Maybe it’s a case of agree and commit, since it can’t really be walked back.

Various prominent people have said years after that .await was the correct choice after all

I was initially very against postfix await and I was wrong. It's great.

Re: Async Rust never left the MVP state

#232

Agree with the other commenters that the title is a bit too dramatic. The content was well written and got the point across. I still don’t have enough experience to have a strong opinion on Rust async, but some things did standout. On the good side, it’s nice being able to have explicit runtimes. Instead of polluting the whole project to be async, you can do the opposite. Be sync first and use the runtime on IO “edge…

What's the alternative? I'm happy to use tokio, but i'm happy other folks can enjoy other executors (smol, async-std, glommio, etc). I think the situation is OK because tokio is well-maintained, even though it's not part of the standard library, and i'm afraid making it part of the standard library would make it harder to use other executors, and harder to port the standard library to other platforms. But maybe my fe…

The best alternative, by far, is don't require async. Async is much harder to work with than other methods of gaining concurrency, and its benefits (like not needing OS context switches) are irrelevant to most developers. There is no good reason that the majority of Rust libraries force their users into async in all its messiness.

Re: Async Rust never left the MVP state

#233
post #158

Earlier quoted context omitted.

When you block the OS does the same thing - yields to other threads.

And how much slower is that? What happens when I run a thousand async tasks? I'll give you a hint, with async/await, it has barely any overhead.

The vast, vast majority of programmers are going to be writing software where there are only a handful of threads (if that). The "I need thousands of concurrent executions" case is simply not relevant to most people.

Re: Async Rust never left the MVP state

#234
post #206

Earlier quoted context omitted.

Does it, though? Whether your function has the `async` keyword attached or has a function argument of type `IO` doesn't really change anything substantial. The whole "function color" argument seems pretty overblown to me. You can't call `foo(int, string)` if you don't have both an int and a string, so is it now a different "color" than the function `bar(int)`? If you want to call `foo` from `bar`, you have to somehow…

Yeah, I tend to agree. What does improve quality-of-life substantially is having a proper effect system, especially when it comes to composing higher-order functions. Having to write copies of List.map and List.async_map in the stdlib is a smell, but the real cost is potentially having to duplicate every function in your code that calls either. E.g, if you have the 'async' effect, List.map can work with async functio…

I agree that `async` and other “effects” (we could also mention const, unsafe, etc.) are not very composable in present-day Rust.

I will note, though, that this particular example (iterating over a list asynchronously) is actually where you might really want to do something else, because async allows you to do something fundamentally different: run all in parallel.

Async really shines when you have code that does two or more things and you don’t care about the order in which they finish, and that isn’t really feasible without it.

Re: Async Rust never left the MVP state

#235

Earlier quoted context omitted.

As I understand, "green threads" are also expensive, for example you either need to allocate a large stack for each "thread", or hook stack allocation to grow the stack dynamically (like Go does), and if you grow the stack, you might have to move it and cannot have pointers to stack objects.

works fine in Go. Yes, you're not getting Rust performance (tho good part of it is their own compiler vs using all LLVM goodness) but performance is good enough and benefits for developers are great, having goroutines be so cheap means you don't even need to do anything explicitly async to get what you want

Rust can be used in contexts like dynamic linkers, kernels, libc, microcontrollers, dynamic libraries, and all sorts of places go has no business running. And it can use async in many of them. Go works fine for many contexts but we already have languages like go that work for those contexts. Rust is for the contexts it doesn't work well for. It's painful that it keeps being pushed to support things that would make it more difficult to support the areas it is unique in supporting.

Re: Async Rust never left the MVP state

#236
post #158

Earlier quoted context omitted.

And how much slower is that? What happens when I run a thousand async tasks? I'll give you a hint, with async/await, it has barely any overhead.

The vast, vast majority of programmers are going to be writing software where there are only a handful of threads (if that). The "I need thousands of concurrent executions" case is simply not relevant to most people.

You do realize what servers do in parallel right? Async/await allows ASP.NET to scale beyond 1 thread per request.

Re: Async Rust never left the MVP state

#237

Earlier quoted context omitted.

What's the alternative? I'm happy to use tokio, but i'm happy other folks can enjoy other executors (smol, async-std, glommio, etc). I think the situation is OK because tokio is well-maintained, even though it's not part of the standard library, and i'm afraid making it part of the standard library would make it harder to use other executors, and harder to port the standard library to other platforms. But maybe my fe…

> What's the alternative? Traits in the stdlib for common functionality like "spawn" (a task) and things like async timers. Then executors could implement those traits and libraries could be generic over them.

100% this

How nice would it be if there were ReadAsync and WriteAsync traits in the standard library.

Right now, every executor (and the futures crate) implements their own and there are compat crates to bridge the gaps.

Re: Async Rust never left the MVP state

#238
post #167

Earlier quoted context omitted.

> Regular code was already async. When you need to wait for an async operation, the thread sleeps until ready and the kernel abstracts it away Not really. I’ve observed async code often is written in such a way that it doesn’t maximize how much concurrency can be expressed (eg instead of writing “here’s N I/O operations to do them all concurrently” it’s “for operation X, await process(x)”). However, in a threaded wor…

> work stealing executors have long been known to offer significantly lower latency with more consistent P99 than traditional threads. This has been known since forever - in the early 00s Well, we know how to make "traditional threads" fast, with lower latency and more consistent P99 since forever^2, in the early 90s. [1] Sure, we can't convince that Finnish guy this is worthwhile to include in THE kernel, despite si…

>despite similar ideas had been running in Google datacenters for idk how many years

I guess this is referring to https://www.youtube.com/watch?v=KXuZi9aeGTw ?

Re: Async Rust never left the MVP state

#239

Earlier quoted context omitted.

> the thread sleeps until ready and the kernel abstracts it away. Sure, but once you involve the kernel and OS scheduler things get 3 to 4 orders of magnitude slower than what they should be. The last time I was working on our coroutine/scheduling code creating and joining a thread that exited instantly was ~200us, and creating one of our green threads, scheduling it and waiting for it was ~400ns. You don't need to w…

You involve the kernel also when you are doing async io. In this context the interesting thing to measure would be doing IO in your green threads vs OS threads. A stronger theoretical performance argument for async io is that you can do batching, ala io_uring, and do fewer protection domain crossings per IO that way.

Well yeah of course, using APIs io_uring and grand central dispatch is basically the whole point of all this async stuff in a systems programming language. It’s absurd it hasn’t been mentioned more here.

OS Threads are for compute parallelism, async with stackless coroutines (ideally) or green threads is for IO parallelism. It’s pretty straight forward.

And IMO, Zig has show how to do async IO right (the foundational stuff. Other languages could add better syntax for ergonomics.

Re: Async Rust never left the MVP state

#240

Earlier quoted context omitted.

I may have missed something, but how does “sans-io” deal with CPU heavy code? For example, if there’s some heavy decoding/encoding required on the data? Does the event loop only drive the network side and the heavy part is done after the loop is finished?

This is a great question and there isn't a definitive answer provided in the sources I linked. Broadly I think there are three approaches: 1. For frequent and small CPU heavy tasks, just run them on the IO threads. As long as you don't leave too long between `.await` points (~10ms) it seems to work okay. 2. Run your sans-io code on a dedicated CPU thread and do IO from an async runtime. This introduces overhead that…

Realised all of these examples are for async, but they apply equally for sync.
Post reply on HN