Defining async is hard. And I'm writing this as one of the many people who designed async in JavaScript. I don't quite agree with the definition in this post: just because it's async doesn't mean that it's correct. You can get all sorts of user-land race conditions with async code, whether it uses `async`/`await` (in languages that need/support it) or not. My latest formulation (and I think that it still needs work)…
The important thing to me is to distinguish between the abstract concept of asynchronism and how it can be implemented, and by the latter I mean both at the abstract level of a programming language and by technical coordination means in a machine. For the abstract concept at the highest level, well, it is just the dual of synchronism: two (or more) parties that somehow need to work together (i.e., one has a dependenc…
Asynchrony is not concurrency
171–180 of 228 posts
Re: Asynchrony is not concurrency
#172The thing that bothers me in general about asynchronous code is how you test it so that you know with some confidence that if it passes the tests today you have replicated all the scenarios/orderings that might happen in production.
You have this same problem with threads of course and I've always found multithreaded programs to be much harder to write and debug....such that I personally use threading only when I feel I have to.
The actual problem with it is that caution is communicating it to developers. I recently had to work on a python system where the developers were obviously doing Javascript half the time. So ... hooray.... they put out a huge changeset to make the thing async....and threaded. Oddly enough none of them had ever heard of the GIL and I got the feeling of being seen as an irritating old bastard as I explained it to their blank stares. Didn't matter. Threading is good. Then I pointed out that their tests were now always passing no matter if they broke the code. Blank stares. They didn't realise that mangum forced all background tasks and async things to finish at the end of an HTTP request so their efforts to shift processing to speed up the response were for nothing.
Knowing things doesn't always matter if you cannot get other people to see them.
Re: Asynchrony is not concurrency
#173Earlier quoted context omitted.
I am not deep into the matter but I would have given the answer: Async code is making code that would have been blocking non-blocking in a manner other stuff can still happen while it is being completed. Since I work a lot in embedded loops where long running blocking snippets could literally break your I/O, lead to visible/audible dropouts etc. this would be the obvious answer.
But that's the thing: async, by itself, doesn't guarantee that anything is non-blocking. For your fiber (or any other kind of user-land abstraction) to be non-blocking, you MUST ensure that it doesn't perform any blocking call. All async does is give you (some of) the tools to make code non-blocking.
Re: Asynchrony is not concurrency
#174Earlier quoted context omitted.
Can confirm. In JS, we designed `await` specifically to hide `.then()`, just as we had designed `.then()` because callbacks made tracking control flow (in particular errors) too complex.
How is that any better to have await? Any resources I might consult on this?
I recall that one of our test suites was tens of thousands of lines of code using `then()`. The code was complicated enough that these lines were by and large considered write-only, partly because async loops were really annoying to write, partly because error-handling was non-trivial.
I rewrote that test suite using `Task.spawn` (our prototype for async/await). I don't have the exact numbers in mind, but this decreased the number of LoC by a factor of 2-3 and suddenly people could see the familiar uses of loops and `try`/`catch`.
Re: Asynchrony is not concurrency
#175I think it's a great idea to not have to have two libraries - so its a "tick" from me for any idea that permits it. The thing that bothers me in general about asynchronous code is how you test it so that you know with some confidence that if it passes the tests today you have replicated all the scenarios/orderings that might happen in production. You have this same problem with threads of course and I've always found…
In distributed systems, it gets worse. For example, when designing webhook delivery infrastructure, you’re not just dealing with async code within your service but also network retries, timeouts, and partial failures across systems. We ran into this when building reliable webhook pipelines; ensuring retries, deduplication, and idempotency under high concurrency became a full engineering problem in itself.
That’s why many teams now offload this to specialized services like Vartiq.com (I’m working here), which handles guaranteed webhook delivery with automatic retries and observability out of the box. It doesn’t eliminate the async testing problem within your own code, but it reduces the blast radius by abstracting away a chunk of operational concurrency complexity.
Totally agree though – async, threading, and distributed concurrency all amplify each other’s risks. Communication and system design caution matter more than any syntax or library choice.
Re: Asynchrony is not concurrency
#176Earlier quoted context omitted.
But that's the thing: async, by itself, doesn't guarantee that anything is non-blocking. For your fiber (or any other kind of user-land abstraction) to be non-blocking, you MUST ensure that it doesn't perform any blocking call. All async does is give you (some of) the tools to make code non-blocking.
cries in Python asyncio
If you look on the bright side, it looks like free-threading is approaching, and OCaml has demonstrated how, by removing the GIL and adding exactly one primitive, you can turn a powerful enough language into a concurrency/parallelism powerhouse with minimal user-visible changes!
Re: Asynchrony is not concurrency
#177Earlier quoted context omitted.
Can confirm. In JS, we designed `await` specifically to hide `.then()`, just as we had designed `.then()` because callbacks made tracking control flow (in particular errors) too complex.
How is that any better to have await? Any resources I might consult on this?
a().then(() =>
b())
.then(() =>
c())
Compared to await a()
await b()
await c()
Even for this simple case I think it's much clearer. Then look at a more complex case: for( i=0; i
Now try re-writing this with then() and see the difference.Re: Asynchrony is not concurrency
#178Earlier quoted context omitted.
But that's the thing: async, by itself, doesn't guarantee that anything is non-blocking. For your fiber (or any other kind of user-land abstraction) to be non-blocking, you MUST ensure that it doesn't perform any blocking call. All async does is give you (some of) the tools to make code non-blocking.
Yeah, sure I mean in embedded-land any async snippet could perform any number of things, like firing a delay command that puts the whole processor to sleep. This could potentially be avoided by clever enough compilers or runtimes, but I am not sure whether that would really be benefitial. I am a fan of making things explicit, so the closer peoples idea of what aync is and what it isn't matches reality the better. Alt…
There used to be a few compilers that used static analysis to predict the cost of a call (where the cost of I/O was effectively considered infinite) and in which you could enforce that a branch only had a budget of N. Modern architectures tend to mess up with any finite value of N, but you could fairly easily adapt such techniques to detect unbounded values.
Re: Asynchrony is not concurrency
#179So "cooperative multitasking is not preemptive multitasking". The typical use of the word "asynchronous" means that the _language is single-threaded_ with cooperative multitasking (yield points) and event based, and external computations may run concurrently, instead of blocking, and will report result(s) as events. There is no point in having asynchrony in a multithreaded or concurrent execution model, you can use b…
While this is indeed the most common use, I'll bring as counter-examples Rust (or C#, or F#, or OCaml 5+) that supports both OS threads and async. OS threads are good for CPU-bound tasks, async for IO-bound tasks. The main benefit of having async (or Go-style M:N scheduling) is that you can afford to launch as many tasks/fibers/goroutines/... as you want, as long as you have RAM. If you're using OS threads, you need…
Some have argued that the real solution to this problem is to "just" fix OS threads. Rumor has it Google has done exactly this, but keeps it close to their chest:
https://www.youtube.com/watch?v=KXuZi9aeGTw
https://lwn.net/Articles/879398/
Somewhat related and also by Google is WebAssembly Promise Integration, which converts blocking code into non-blocking code without requiring language support:
I see a possible future where the "async/await" idea simply fades away outside of niche use-cases.
Re: Asynchrony is not concurrency
#180I think it's a great idea to not have to have two libraries - so its a "tick" from me for any idea that permits it. The thing that bothers me in general about asynchronous code is how you test it so that you know with some confidence that if it passes the tests today you have replicated all the scenarios/orderings that might happen in production. You have this same problem with threads of course and I've always found…
That resonates. Testing asynchronous and multithreaded code for all possible interleavings is notoriously difficult. Even with advanced fuzzers or concurrency testing frameworks, you rarely gain full confidence without painful production learnings. In distributed systems, it gets worse. For example, when designing webhook delivery infrastructure, you’re not just dealing with async code within your service but also ne…
It would be nice to add a disclaimer that this is a system you're working on.