4 ms·
Async programming is beautiful. It’s the easiest and most natural way to do multiple things at the same time in single threaded code. Async makes things possib
by andrewstuart 3y ago
Async programming is beautiful. It’s the easiest and most natural way to do multiple things at the same time in single threaded code.
Async makes things possible that are hard or impossible to do with synch programming.
It’s a real game changer for python especially. Cant comment on rust, hopefully its implementation is smooth.
- nsm 3y agoAsync/await is a _concurrency_ mechanism, and concurrency is certainly naturally useful. However async/await is certainly not the best implementation of concurrency, except in the narrow design space Rust has chosen. If you have a language with a runtime, green threads/fibers/coroutines, along with a choice mechanism is really the way to go. It trades off some performance for much better ergonomics. Go, Java, Racket all use this. It is unfortunate that Python picked async/await.
- WaxProlix 3y agoI mostly agree, but I think you can still just pip install gevent and have greenlets as you always did - just not as language 'primitives'. Personally I've never liked the syntactic sugar on top of function calls very much. If something is a promise or whatever, return me the promise and I can choose what to do with it.
- TwentyPosts 3y agoIs it really though? All I personally care for when it comes to "doing multiple things at the same time" is frankly Rust's scoped threads API: Create N threads, have them perform some computations, then join them at the end of the scope. How is this not more natural than creating various state machines and passing around all sorts of weird highly abstract Future-objects?
- andrewstuart 3y agoThreads are far more heavy than async. Async code maximizes the potential of the thread it’s running in.
- TwentyPosts 3y ago> Threads are far more heavy than async This sounds like an issue with the implementation of threads and scheduling in common operating systems, and I don't see how replicating all that functionality inside of each sufficiently large programming language is remotely taken seriously. But also, you didn't respond to what I even said. You claimed that async is 'beautiful and natural'. I disagreed. You...fell back to a performance claim that's uncontroversially true, but irrelevant to what I said.
- coffeemug 3y agoWhen you're reading code, it's really really nice to be able to tell if a line of code blocks. Other than that `Thread.new(_ => doIO()).join()` is pretty much the same as `await doIO()`.
- andrewstuart 3y agoThere's no concurrency issues with async programming. No race conditions, no inter thread coordination, no concerns about all the weird shit that happens when doing multi threading.
- dannymi 3y agoOne of the main reasons to use async in the first place is to distribute the work to all the cpu cores that you have. So you will still have all the concurrency issues with async in that case. Only if you limited async to only one thread on one core (why would you do that?) you could avoid that.
- andrewstuart 3y ago>> One of the main reasons to use async in the first place is to distribute the work to all the cpu cores that you have Errrr..... no it's not. Your statement is flat out wrong. async is single threaded. You're not really understanding async. async is single threaded. If you want to maximise your cores then run multiple instances of a single threaded process using systemd or something, or use your application to launch multiple async threads. You can, in python and probably in Rust, run an executor, which essentially is running a synchronous process in a thread to make some bit of synchronous work compatible with async, but that's not really ideal and it's certainly not the purpose of async.
- sunshowers 3y agoFor the limited case of data-parallel computations as you're describing, you don't need async. However, many real-world programs are inherently complicated state machines, where each individual state waits on one or more nested state machines to progress and/or complete -- async is often the most reasonable way to express that. I wrote a post detailing a non-trivial production example use of async that might be interesting, regarding the cargo-nextest test runner that I wrote and maintain: https://sunshowers.io/posts/nextest-and-tokio/ https://sunshowers.io/posts/nextest-and-tokio/. Nextest is not "web-scale" (c10k), since the number of tests one is concurrently running is usually bounded by the number of processor hyperthreads. So the fact that async tasks are more lightweight than OS threads doesn't have much bearing in this case. But even beyond that, being able to express state machines via async makes life so much simpler. Over a year after switching nextest to using async, I have no regrets. The state machine has gotten around twice as complicated since then--for example, nextest now handles SIGTSTP and SIGCONT carefully--and async has coped admirably with it. (There are currently somewhat serious issues with Rust async, such as a really messy cancellation story. But that's generally not what gets talked about on places like HN.)
- mplanchard 3y agoNot who you’re replying to, but this is great context, and I want to thank you for including it. As another heavy async user (for a network service that handles loads of requests and does loads of DB reads and writes), I am also a big fan of Rust’s async at scale. We’re currently in the process of seeing where we can get rid of async_trait with 1.75, which has not been particularly drop-in in many cases but which is still exciting. Anyway, I have been meaning to try out nextest for our big honking monorepo workspace at work. The cargo test runner has always been essentially fine for our needs, but speeding up test execution in CI could be a huge win for us.
- sunshowers 3y agoI'd love to hear how it goes!
- TwentyPosts 3y ago
- bvrmn 3y ago> It’s a real game changer for python especially Python is so slow you gain nothing with async. I have a plenty of cool stories how I've fixed crumbled products because they were async and all connection load instead of nginx/backend goes directly into db. You rarely need long connections and if you choose async for python because it's fast then it's a wrong choice because it's not. BTW asyncio is awful bloated implementation with huge overhead around task management.
- andrewstuart 3y ago>> Python is so slow you gain nothing with async. It’s not necessarily about speed, though this statement above is flat out wrong. async in Python allows you to build different types of applications. For example you can attach a task to stdout of another process and read and process it.
- bvrmn 3y ago> For example you can attach a task to stdout of another process and read and process it. How max many processes you handled in this fashion? The catch is: if you need thousands than asyncio has too much overhead and you need manual epoll. If less threads are much easier to use and acceptable performance wise.