[HN Gopher] A Visual Journey Through Async Rust
___________________________________________________________________
A Visual Journey Through Async Rust
Author : PaulHoule
Score : 137 points
Date : 2025-04-25 00:50 UTC (22 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| OskarS wrote:
| Very neat visualizations! Really good way to demonstrate the
| underlying principles. Great article.
|
| I will add one thing: the author makes much of how problematic
| CPU-intensive tasks are. That's true, but also: if you need to do
| a CPU-intensive operation, you need to tie up a CPU to do it,
| there's no getting around it. What you might want to do is break
| the computation up in to smaller chunks with `.await`s sprinkled
| in there or dispatch it to a background thread, but at some point
| you have to pay the cost in CPU time.
|
| What is much more problematic is blocking I/O operations. That
| also ties up a CPU and blocks the event loop, but for no good
| reason. All the CPU is going to be doing is sleeping waiting for
| the network or hard-drives or whatever it is to do it's work,
| when it could be doing other useful things, processing other
| events. That kind of thing leads to huge under-utilization of
| your resources, and it kills your concurrency.
|
| This means you really can't mix async I/O with blocking I/O: if
| you go async, ALL your I/O operations need to be async. Or you
| have to do it off the event loop in a background thread or
| something, but then you're losing all the benefits of using async
| in the first place.
| remram wrote:
| > blocking I/O operations. That also ties up a CPU and blocks
| the event loop
|
| They do block the event loop (if single-threaded) but they do
| not "tie up" a CPU (core), the OS will schedule other threads
| on it.
| binary132 wrote:
| assuming you have other threads
|
| but in an async I/O server scenario, the typical architecture
| is a fixed-size pool of worker threads, which ideally
| entirely occupy a single core each. therefore, if one of
| those threads is blocked, that core is wasted.
| PaulHoule wrote:
| I went through a phase of writing a lot of little things in
| async Python which was a lot of fun but I wrote an app that
| really tied up the event loop and now, at least for web
| servers, I develop with Flask, deploy to gunicorn and often
| front with IIS or nginx to serve up images and big files now.
|
| One thing I still like async Python for is programs that have a
| number of polling tasks going on at a slow cadence, say once a
| minute or less, where it doesn't really matter to me if a task
| gets delayed 5 seconds because of another task. In that case
| writing a number of tasks that await.sleep is easy and fun and
| works great -- I'll use async io in the tasks if it is easy to
| do so but if I use blocking I/O and it blocks... no problem.
|
| At work I've been writing web servers in Java (or C#) for a
| couple of jobs and between threads and the garbage collector I
| also think it is easy and fun. Sure if I was handling Google-
| levels of traffic I might think differently, but threads scale
| pretty well for 99% of the web sites out there. Java gives you
| all the right primitives to do common tasks: sometimes I code
| something up with an Executor in 20 minutes and it works right
| the first time and gets a 14x speedup with 16 cores, somebody
| else tries Actors in the language of the day and spends a few
| days on it, never gets more than a 3x speedup and gets a
| different answer every time. (Threaded programming is easy
| _when you have a rich primitive library_ you get in trouble
| when you get it in your head that it is noble to build
| everything in scratch from a small set of primitives)
|
| Java even has virtual threads that play well with real threads
| if real threads aren't good enough for you.
| vermilingua wrote:
| It's never addressed in the article that the calculations running
| on spawned threads produce deformed sine curves. Is that just a
| result of how its plotted or do tokio threads have less accurate
| track of time?
| alphaXp wrote:
| Thats a good observation. I believe the deformation comes from
| the variable runtime of the sin method. Even with the 100
| micros sleep that I've put there, in reality it takes a
| different amount of time between each data point calculation,
| making the sine wave a bit wonky. This gets worse as more and
| more calculations are done in parallel
| ninkendo wrote:
| It's more likely to be the unaccuracy of Instant in rust.
| It's guaranteed to be non-decreasing, but not steady:
| https://doc.rust-lang.org/std/time/struct.Instant.html
|
| > In other words, each tick of the underlying clock might not
| be the same length (e.g. some seconds may be longer than
| others). An instant may jump forwards or experience time
| dilation (slow down or speed up), but it will never go
| backwards
| LoganDark wrote:
| I think it's just scheduling. The deformation is when it didn't
| get to run exactly in time because Tokio had to wake up enough
| other tasks first.
| jayd16 wrote:
| Looks like it's just plotting a fixed number of points at the
| time the iteration was scheduled. It's not trying to map a
| smooth curve.
| inglor wrote:
| > Unlike Node.js, Rust's Tokio allows us to spawn a new Task and
| run futures within it.
|
| Nice article! For future reference in Node.js this would be
| `worker_threads` or if you want a higher level tokio like API
| something like https://piscinajs.dev/
|
| This has been possible in Node.js for quite a while
|
| --
|
| Also for blocking I/O CPU bound parallelism I've found Rayon to
| be a pleasure. It has a few caveats but it leverages the Rust
| race condition checking well and it's very ergonomic.
|
| I happily mix it with `tokio` in an application that is CPU bound
| but has to perform some async I/O (due to the SDKs it uses)
| remram wrote:
| A tokio task is not a thread
| SkiFire13 wrote:
| > piscinajs
|
| Lmao this wordplay made my day
|
| > Rust race condition checking
|
| Nit: Rust does not prevent race conditions, it prevents data
| races.
| rc00 wrote:
| Shared 12 days ago: https://news.ycombinator.com/item?id=43675098
| binary132 wrote:
| This is not limited only to Rust and I'd be very curious to see a
| similar comparison across multiple runtimes!
| jwufasdfsds wrote:
| The async disaster can be avoided by using Plan9 or Inferno.
|
| Don't misinterpret this as criticism of async-rust. It's required
| to work on legacy platforms like linux.
| whytevuhuni wrote:
| This is obviously a troll comment, but it made me curious.
|
| I'm familiar with Plan 9, and I know about the interesting
| mount namespace shenanigans you can pull off with it, but does
| it actually have anything that would help with async?
| jdnier wrote:
| > Alright! We managed to plot two sine waves in the most
| convoluted method ever!
|
| Those sine waves start to resemble a multi-voice music score. You
| might get some interesting pitch variability depending on other
| processes that are running.
| ModernMech wrote:
| "Visualizing futures runtime like this really makes some pennies
| drop."
|
| What's it mean to drop pennies?
| masfuerte wrote:
| It's a British idiom. When the penny drops you suddenly
| understand something.
|
| https://en.wiktionary.org/wiki/the_penny_drops
| tialaramex wrote:
| I was kinda hoping for a origin story, but alas this doesn't
| seem to lead to one, and then I checked an actual physical
| paper dictionary (I'm an old man, old enough that I bought a
| dictionary in 1982 apparently) and that does define this
| phrase but doesn't explain where it came from.
|
| I have used this metaphor my whole life without thinking
| about why pennies dropping have this significance. So now I'm
| wondering
|
| My best guess is that it's thinking about mechanisms which
| operate when given money, a topical example would be the
| Alzara fortune telling machine in a Rumpus Room of Blue
| Prince. If we put a coin in the machine, it springs into life
| and tells us... something. If you won't give it a coin,
| nothing for you.
| ModernMech wrote:
| I managed to find this at least: The penny
| drops means sudden understanding or realisation of
| something or other. The expression usually implies a period
| of non-comprehension before the penny drops and derives
| from early penny slot machines in which the coin or coins
| took quite some time to drop. That is why the expression is
| sometimes in the form of 'the penny has finally dropped'.
| The OED cites the 1940s as the first appearance of the
| figurative meaning. Penny slot machines first appeared
| during the mid-19th century and some alternative sources
| date the current figurative meaning from at least the
| 1920s, if not earlier.
|
| https://idiomorigins.org/origin/penny-drops
|
| Sounds like your intuition is correct, and the phrase comes
| in particular from the delay in the penny takes to drop in
| these machines. I'd imagine if they were faster probably
| the phrase wouldn't have developed, so an interesting
| example of how some engineers somewhere who designed the
| slow mechanism ended up impacting the lexicon.
___________________________________________________________________
(page generated 2025-04-25 23:01 UTC)