This remind me of the blog post "What Color is Your Function?"[0], they had to create a different library that is the same as the standard library but with async functions. I thought Rust had other, better ways to create non-blocking code so I don't understand why to use async instead. [0] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
This is why I'm curious about algebraic effects which was recently discussed on /r/rust [0] The main challenges I see are around usability within the language design on how best to propagate and compose them. [0] https://www.reddit.com/r/rust/comments/cjcwmu/is_there_inter...
Async-std: an async port of the Rust standard library
211–220 of 238 posts
Re: Async-std: an async port of the Rust standard library
#212Earlier quoted context omitted.
Let's be real here, its not just the memory requirements, because context switching and the associated nuking of cpu caches are not free. You can go very far with it nowadays, but you can go much farther with async code, if you really need to.
Nobody is denying that async code is faster. But it’s not as dramatic as presented in the grand parent post. And IMHO the added code complexity is not worth the trouble.
With a simulated load of ~20 users we were running over 1000 threads.
Several posts in the chain say that 20k+ threads is "fine". Not unless you have a ton of cores. The memory and context switching overhead is gigantic. Eventually your server is doing little besides switching between threads.
We had to rewrite our s3 code to use async, now we can do many thousands of concurrent uploads no problem.
Other places we've had to use async is a proxy that intercepts certain HTTP calls and user stats uploader that calls third party analytics service.
Just sayin it's not that unusual to need async code because threading overhead is too high
Re: Async-std: an async port of the Rust standard library
#213Earlier quoted context omitted.
They are very similar. In cooperative multitasking, programs yield the thread to the OS, while async programs yield to the event loop. In both cases, yielding is voluntary. Are there other differences? It's probably quite easy to turn a program written one way into the other. Edit: I just remembered that in cooperative multitasking, it's probably possible for the OS to safely save the program stack pointer, meaning t…
Even conceptually the models are very different, in one control is just given up and regained unpredictably, while in the other one it is programmed, hence asynchronous programming, not multitasking.
Re: Async-std: an async port of the Rust standard library
#214Earlier quoted context omitted.
> in one control is just given up and regained unpredictably Which one? It’s “cooperative” ie not unpredictable. The points where one can block are predictable and documented explicitly, otherwise how would the programmer know they won’t block forever. The same should hopefully be the case for async/awaitable apis. In fact where async/await will actually give up control are harder to tease out. The differences are re…
In cooperative multitasking you can program when to give up control, not when it is regained. The regaining part is unpredictable. Which introduces a lot of non-determinism to deal with and overhead.
Re: Async-std: an async port of the Rust standard library
#215Earlier quoted context omitted.
Nobody is denying that async code is faster. But it’s not as dramatic as presented in the grand parent post. And IMHO the added code complexity is not worth the trouble.
We have some pretty vanilla file upload code that needs async. S3 latency is fairly high. If you're uploading a few tiny files per user per second, thread usage gets out of hand real fast. With a simulated load of ~20 users we were running over 1000 threads. Several posts in the chain say that 20k+ threads is "fine". Not unless you have a ton of cores. The memory and context switching overhead is gigantic. Eventually…
Re: Async-std: an async port of the Rust standard library
#216Earlier quoted context omitted.
> And IMHO the added code complexity is not worth the trouble. The thing is, this is just that - your opinion, generalized as The Truth. But engineering is about making the right trade-offs. Often threading will be fine, you'll win simplicity, and all is good. But sometimes you really need the performance, or your field is crowded and its a competitive advantage. Think large-scale infrastructure at AWS, central load-…
It goes deeper than that. There is plenty of research showing that shared memory multithreading is not even a viable concurrency model. The premise that threads are fine and simple is just false.
Re: Async-std: an async port of the Rust standard library
#217Earlier quoted context omitted.
> in one control is just given up and regained unpredictably Which one? It’s “cooperative” ie not unpredictable. The points where one can block are predictable and documented explicitly, otherwise how would the programmer know they won’t block forever. The same should hopefully be the case for async/awaitable apis. In fact where async/await will actually give up control are harder to tease out. The differences are re…
In cooperative multitasking you can program when to give up control, not when it is regained. The regaining part is unpredictable. Which introduces a lot of non-determinism to deal with and overhead.
I don’t see how this increases overhead to deal with either.
Basically, coop multitasking and async/await operate on the exact same execution framework, the latter just gives convenient syntactic support.
Perhaps you should see how typescript turns async await into js.
Re: Async-std: an async port of the Rust standard library
#218Earlier quoted context omitted.
Thanks. Helpful. My question is, in this example: result = await server.getStuff() second = await server.getMoreStuff(result+1) print(result) `await getStuff()` MUST terminate before `await getMoreStuff() ` begins. So this chunk alone is analagous to synchronous code, unless we're in the middle of a spawned task, and there are other spawned tasks in the executor that can be picked up.
Yes, the idea is that the thread that is executing this piece of code can "steal" other work when it is awaiting on either of those methods. Frankly, in the case of sequential flow like the above, I would rather write result = server.getStuff() second = server.getMoreStuff(result+1) print(result) and have the runtime automatically perform work-stealing for me. No need for awaits. They just litter the code. This is wh…
Gevent in Python does something similar [implicit switching] using a dirty monkeypatching. It is great while it works. Sooner or later the explicit cooperative concurrency such as provided by async/await syntax wins (e.g., asyncio, trio, curio Python libraries)
Re: Async-std: an async port of the Rust standard library
#219Earlier quoted context omitted.
Green threads have no place in a low level systems language like Rust whose design goals are zero cost abstraction and trivial C interop. D made a similar mistake by requiring GC/runtime from start and now even though they added ways to avoid it the ecosystem and the language design are "poisoned" by it an itmakeas it a very hard sell in some places where it could be sold as a C++ successor. Because rust made the rig…
Many systems have been developed in systems enabled GC languages. C++11 introduced a GC API in the standard library, and one of the biggest C++ game engine does use GC in their engine objects, Unreal. C++ on Windows makes heavy use of reference counting (which is a GC algorithm from CS point of view), via COM/UWP. The biggest problem to overcome is religious, not technical.
Not sure if Ref counting is a good example here, as there is no runtime monitoring the object graph hierarchy and of course Rust it’s self uses ref counting in many situations.
Re: Async-std: an async port of the Rust standard library
#220Earlier quoted context omitted.
Except that io_uring is threads running in kernel. There is no true async I/O on most (if not all) current platforms - it's all threads, either in user space or in kernel space. Sometimes even deliberately, for example polling disk will give better latency compared to waiting for IRQ.
O_DIRECT + aio on Linux seems okay for preallocated files, no?
If you mean io_submit, then yes, but in vast majority of cases, actual `io_submit` syscall will block, because of metadata updates, unaligned reads, etc ...