Live data from Hacker News

What async promised and what it delivered

causality.blog

161–170 of 317 posts

Re: What async promised and what it delivered

#161
post #110

Earlier quoted context omitted.

On a 64-bit system, 10 GB of address space is nothing.

10 GB of RAM is certainly something though. Especially in current times.

Except if those threads are actually faulting in all of that memory and making it resident, they'd be doing the same thing, just on the heap, for a classic async coroutine style application.

Re: What async promised and what it delivered

#162
post #87

> Language designers who studied the async/await experience in other ecosystems concluded that the costs of function coloring outweigh the benefits and chose different paths. Not really. The author provides Go as evidence, but Go's CSP-based approach far predates the popularity of async/await. Meanwhile, Zig's approach still has function coloring, it's just that one color is "I/O function" and the other is "non-I/O f…

In my experience people complain about it because they are coming from a blocking first mindset. They're trying to shoehorn async calls into an inherently synchronous structure.

A while back I just started leaning in. I write a lot of Python at work, and anytime I have to use a library that's relies on asyncio, I just write the entire damn app as an asynchronous one. Makes function coloring a non-issue. If I'm in a situation where the two have to coexist, the async runtime gets its own thread and communication back and forth is handled at specific boundaries.

Re: What async promised and what it delivered

#164

> OS threads are expensive: an operating system thread typically reserves a megabyte of stack space Why is reserving a megabyte of stack space "expensive"? > and takes roughly a millisecond to create I'm not sure where this number is from, it seems off by a few orders of magnitude. On Linux, thread creation is closer to 10 microseconds.

The author doesn't fully justify the assertion but it does have sound basis.

While virtual memory allocation does not require physical allocation, it immediately runs into the kinds of performance problems that huge pages are designed to solve. On modern systems, you can burn up most of your virtual address space via casual indifference to how it maps to physical memory and the TLB space it consumes. Spinning up thousands of stacks is kind of a pathological case here.

10µs is an eternity for high-performance software architectures. That is also around the same order of magnitude as disk access with modern NVMe. An enormous amount of effort goes into avoiding blocking on NVMe disk access with that latency for good reason. 10µs is not remotely below the noise floor in terms of performance.

Re: What async promised and what it delivered

#165

Earlier quoted context omitted.

1 megabyte stacks mean ten thousand threads require 10 gigabytes of RAM just for the stacks . The entire point of the asynchronous programming paradigm is to reclaim all of those gigabytes by not allowing stacks to develop at all, by stealthily turning everything into a hidden form of cooperative multitasking instead.

Only if they're resident. Otherwise you just need one page per thread of physical memory (so ~40MB on x86) and 10GB of virtual memory.

While that's strictly true, resident memory in this context is a function of worst case memory usage by the code executing on those stacks. Seems wise to assume worst case performance when discussing this.

The program could use one page's worth of stack space, which is optimal. The program could use like 200 bytes of stack space, which wastes the rest of the page. The program could recurse all the way to 9.9 MB of stack usage, stop just before overflow and then unwind back to constant 200 bytes stack space usage, and never touch all those pages ever again.

Re: What async promised and what it delivered

#167
post #143

Earlier quoted context omitted.

Data race != Race condition

Data races are a specific race condition - they may be safe or cause tearing. Serially, completely synchronously overwriting values is none of these categories though.

You're mixing up quite a few somewhat related but different concepts: data races, race conditions, concurrency and parallelism.

Concurrency is needed for race conditions, parallelism is needed for data races. Many single threaded runtimes including JS have concurrency, and hence the potential for race conditions, but don't have parallelism and hence no data races.

Re: What async promised and what it delivered

#169

The discussion around async await always focuses on asynchronous use-cases, but I see the biggest benefits when writing synchronous code. In JS, not having await in front of a statement means that nothing will interfere with your computation. This simplifies access to shared state without race conditions. The other advantage is a rough classification in the type system. Not marking a function as async means that the…

Maybe I am missing something. But the function coloring problem is basically the tension that async can dominate call hierarchies and the sync code in between looses it's beneficial properties to a degree. It's at least awkward to design a system that smoothly tries to blend sync that executes fast and async code that actually requires it.

Saying that fs.readSync shouldn't exist is really weird. Not all code written benefits from async nor even requires it. Running single threaded, sync programs is totally valid.

Re: What async promised and what it delivered

#170

I like async and await. I understand that some devs don’t want to learn async programming. It’s unintuitive and hard to learn. On the other hand I feel like saying “go bloody learn async, it’s awesome and massively rewarding”.

It is an intrinsic tradeoff. With async there is significantly more code complexity with substantially higher performance and scalability.

If you don't need the performance and scalability then it is not unreasonable to argue that async isn't worth the engineering effort.

Post reply on HN