Live data from Hacker News

What async promised and what it delivered

causality.blog

71–80 of 317 posts

Re: What async promised and what it delivered

#71
post #58

Earlier quoted context omitted.

Function coloring does not mean that functions take parameters and have return values. Result is not a color. You can call a function that returns a Result from any other function. Errors as return values do not color a function, they're just return values. Async functions are colored because they force a change in the rest of the call stack, not just the caller. If you have a function nested ten levels deep and it c…

You can exit an async/IO monad just like you can exit an error monad: you have a thread blocking run(task) that actually executes everything until the future resolves. Some runtimes have separate blocking threadpools so you don't stall other tasks.

If you have something in a specific language that does not result in having to change the entire call stack to match something about it, then you do not have a color. Sync/async isn't a "color" in all languages. After all, it isn't in thread-based languages or programs anyhow.

Threading methodology is unrelated though. How exactly the call stack is scheduled is orthogonal to the question of whether or not making a call to a particular function results in type changes being forced on all function in the entire stack.

There may also be cases where you can take "async" code and run it entirely out of the context of any sort of sceduler, where it can simply be turned into the obvious sync code. While that does decolor the resulting call (or, if you prefer, recolor it back into the "sync" color) it doesn't mean that async is not generally a color in code where that is not an option. Solving concurrency by simply turning it off certainly has a time and place (e.g., a shell script may be perfectly happen to run "async" code completely synchronously because it may be able to guarantee nothing will ever happen concurrently), but that doesn't make the coloration problem go away when that is not an option.

Re: What async promised and what it delivered

#72
post #47

Earlier quoted context omitted.

async/await came out of C# (well at least the JS version of it). There are a bunch of use cases for it outside of implementing concurrency in a single threaded runtime. Pretty much every GUI toolkit I've ever used was single threaded event loop/GUI updates. Green threads are a very controversial design choice that even JVM backed out of.

> Green threads are a very controversial design choice that even JVM backed out of. Did they? Project Loom has stabilized around Java 21, no?

Virtual Threads aren't quite the same as green threads (they don't block the OS thread) and they work extremely well now.

Re: What async promised and what it delivered

#73

No mention of JVM.. which is a bit odd as recently is kinda solved this problem. Sure, not all use cases, but a lot. It uses N:M threading model - where N virtual threads are mapped to M system threads and its all hidden away from you. All the other languages just leak their abstractions to you, java quietly doesn't. Sure, java is kinda ugly language, you can use a different JVM language, all good. Don't get me wrong…

It is mentioned

Re: What async promised and what it delivered

#74

Async is a Javascript hack that inexplicably got ported to other languages that didn't need it. The issue arose because Javascript didn't have threads, and processing events from the DOM is naturally event driven. To be fair, it's a rare person who can deal with the concurrency issues threads introduce, but the separate stacks threads provide a huge boon. They allow you to turn event driven code into sequential code.…

async/await came out of C# (well at least the JS version of it). There are a bunch of use cases for it outside of implementing concurrency in a single threaded runtime. Pretty much every GUI toolkit I've ever used was single threaded event loop/GUI updates. Green threads are a very controversial design choice that even JVM backed out of.

Yep and I loved when C# introduced it. I worked on a system in C# that predated async/await and had to use callbacks to make the asynchronous code work. It was a mess of overnested code and poor exception handling, since once the code did asynchronous work the call stack became disconnected from where the try-catches could take care of them. async/await allowed me to easily make the code read and function like equivalent synchronous code.

Re: What async promised and what it delivered

#75
post #39

How many systems are there that can't just spawn a thread for each task they have to work on concurrently? This has to be a system that is A) CPU or memory bound (since async doesn't make disk or network IO faster) and B) must work on ~tens of thousands of tasks concurrently, i.e. can't just queue up tasks and work on only a small number concurrently. The only meaningful example I can come up with are load balancers,…

I think it's another case of the whole industry being driven by the needs of the very small number of systems that need to handle >10k concurrent requests.

Re: What async promised and what it delivered

#76

Earlier quoted context omitted.

I think the lesson is to be careful about introducing incompatibility via the type system. When you introduce distinctions, you reduce compatibility. Often that’s deliberate (two functions shouldn’t be interchangeable because it introduces a bug) but the result is lots of incompatible code, and, often, duplicate code. Effects are another way of making functions incompatible, for better or worse. It can be done badly.…

You can also use type inference with union types like ZIO. So you could e.g. return a Result where the error type is `DatabaseError | InvalidBirthdayError`. If you're in an error monad anyway, and you add a new error type deep in the call stack, it can just infer itself into the union up the stack to wherever you want to handle it.

That will help locally, but for a published API or a callback function where you don't know the callers, it's still going to break people if you change a union type. It doesn't matter if it's inferred or not.

Re: What async promised and what it delivered

#77

No mention of JVM.. which is a bit odd as recently is kinda solved this problem. Sure, not all use cases, but a lot. It uses N:M threading model - where N virtual threads are mapped to M system threads and its all hidden away from you. All the other languages just leak their abstractions to you, java quietly doesn't. Sure, java is kinda ugly language, you can use a different JVM language, all good. Don't get me wrong…

It is mentioned

Ah yeah, you are right. It was easy to miss, as it was ~30 words in a massive article.

Re: What async promised and what it delivered

#78
post #39

How many systems are there that can't just spawn a thread for each task they have to work on concurrently? This has to be a system that is A) CPU or memory bound (since async doesn't make disk or network IO faster) and B) must work on ~tens of thousands of tasks concurrently, i.e. can't just queue up tasks and work on only a small number concurrently. The only meaningful example I can come up with are load balancers,…

I'm not sure this is correct mental model of what async solves Async precisely improves disk/network I/O-bound applications because synchronous code has to waste a whole thread sitting around waiting for an I/O response (each with its own stack memory and scheduler overhead), and in something like an application server there will be many incoming requests doing so in parallel. Cancellation is also easier with async C…

I have some test code that runs a comparison of Hyper pre-async (aka thread per request) vs async (via Tokio), and the pre-async version is able to process more requests per second in every scenario (I/o, CPU complex tasks, shared memory).

I'll publish my results shortly. I did these as baselines because I'm testing finishing the User Managed Concurrency Groups proposal to the linux kernel which is an extension to provide faster kernel threads (which beat both of them)

Re: What async promised and what it delivered

#80
> 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.

Post reply on HN