Live data from Hacker News

Async/Await is finally back in Zig

charlesfonseca.substack.com

51–60 of 90 posts

Re: Async/Await is finally back in Zig

#51
post #7

Earlier quoted context omitted.

I really wish people would get over the coloring meme. Knowing if a function will yield the thread is actually extremely relevant knowledge you want available.

This is like saying knowing if you're dealing with NEAR pointers or FAR pointers is extremely relevant. I reject the premise - a model that forces me to think about these things is a degenerate model.

That's fine but the alternatives are insufficient.

Re: Async/Await is finally back in Zig

#52
Async/await feels very misguided to me. It's an extremely complex language feature for something that can be done way better, completely in userspace.

You can implement stackful coroutines yourself in C/C++, you need like 30 lines of assembly (as you can't switch stack pointers and save registers onto the stack from most languages). This is WAY better than what you could do for example with the way more convoluted C++ co_async/co_await for two reasons:

1. Your coroutine has an actual stack - you don't have to allocate a new "stack frame" on the heap for every "stack frame", e.g. every time you call a function and await it.

2. You don't need special syntax for awaiting - any function can just call your Yield() function, which just saves the registers onto the stack and jumps out of the coroutine.

Minicoro [1] is a single-file library that implement this in C. I have yet to dig into the Zig implementation - maybe it's better than the C++/Rust ones, but the fact they call it "async/await" doesn't bring me much hope.

Re: Async/Await is finally back in Zig

#53
post #22

Earlier quoted context omitted.

> The alternatives are callbacks No. The alternative is lightweight/green threads and actors. The thing with await is that it can be retrofitted onto existing languages and runtimes with relatively little effort. That is, it's significantly less effort than retrofitting an actual honest-to-god proper actor system a la Erlang.

> The alternative is lightweight/green threads and actors. How lightweight should threads be to support high scale multitasking? Writing my own language, capturing stack frames in continuations resulted in figures like 200-500 bytes. Grows with deeply nested code, of course, but surely this could be optimized... https://www.erlang.org/docs/21/efficiency_guide/processes.ht... This document says Erlang processes use 30…

I didn't have to answer :) Thank you for looking it up.

Erlang also enjoys quite a lot of optimizations on the VM level. E.g. a task is parked/hybernated if there's no work for it to perform (e.g. it's waiting for a message), the switch between tasks is extremely lightweight, VM internals are re-entrant, employ CPU-cache-friendly data structures, garbage collection is both lightweight and per-thread/task etc.

Re: Async/Await is finally back in Zig

#54
> Despite the completion order varying, each task correctly writes to its designated position in the results array, showing proper concurrent data handling.

Huh? It’s not like the entire array was passed into each task. Each task just received a pointer to an usize to write to.

Where is concurrent data writing in the example?

Re: Async/Await is finally back in Zig

#55
post #13

Someone has historical insights into why async/await seems to have taken over the world? I often write Rust and I don't find it very attractive, but so many good projects seem to advertise it as a "killer feature". Diesel.rs doesn't have async, and they claim that perf improvement may not be worth it ( https://users.rust-lang.org/t/why-use-diesel-when-its-not-as... ). For a single threaded JS program, async makes a l…

Microsoft did some research on it 15-20 years ago for .NET which showed that sync doesn't scale for I/O workloads. The rest of the world sort of "knew" at this point, and all the callback and statemachine hell which came before was also leading the world toward async/await but the Microsoft research kind of formed the foundation for "universal" acceptance. It's not just for single threaded JS programs, you almost never want to tie up your threads even when you can have several of them because it's expensive in memory. As you'll likely see in this thread, some lower level programmers will mention that they prefer to build stackful coroutines themselves. Obviously that is not something Microsoft wanted people to have to do with C#, but it's a thing people do in c/c++ and similar (probably not with C#), and if you're lucky, you can even work in a place that doesn't turn it into the "hell" part.

I can't say why Diesel.rs doesn't need async, and I would like to point out that I know very little about Diesel.rs beyond the fact that it has to do with databases. It would seem strange that, anything, working with databases which an I/O heavy workload would not massively benefit from async though.

Re: Async/Await is finally back in Zig

#56
post #22

Earlier quoted context omitted.

> The alternatives are callbacks No. The alternative is lightweight/green threads and actors. The thing with await is that it can be retrofitted onto existing languages and runtimes with relatively little effort. That is, it's significantly less effort than retrofitting an actual honest-to-god proper actor system a la Erlang.

Isn’t await often just sugar around the underlying implementation be that greenthreads, epoll, picoev, etc?

I think it depends on the language?

Javascript's async/await probably started as a sugar for callbacks (since JS is single-threaded). Many others definitely have that as sugar for whatever threading implementation they have. In C# it's sugar on top of the whole mechanism of structured concurrency.

But I'm mostly talking out of my ass here, since I don't know much about this topic, so everything above is hardly a step above speculation.

Re: Async/Await is finally back in Zig

#57
post #9

Earlier quoted context omitted.

Look at the node.js APIs: readFile, readFileSync, writeFile, writeFileSync ... and on and on. If that's not a meme then I don't know what is.

And the alternative without async-await is ? blocking the event loop or the callback pyramid. Node is one place where async-await has zero counter arguments and every alternative is strictly worse.

> And the alternative without async-await is ? blocking the event loop or the callback pyramid.

No, just callbacks and event handlers (and an interface like select/poll/epoll/kqueue for the OS primitives on which you need to wait). People were writing threadless non-blocking code back in the 80's, and while no one loved the paradigm it was IMHO less bad than the mess we've created trying to avoid it.

One of the problems I'm trying to point out is that we're so far down the rabbit hole in this madness that we've forgotten the problems we're actually trying to solve. And in particular we've forgotten that they weren't that hard to begin with.

Re: Async/Await is finally back in Zig

#58
post #47
post #6

Earlier quoted context omitted.

For one thing, they’re expensive and viral. “Zero overhead” implementations don’t take into account the need for unwind tables. For every function/method that might be thrown across. They’re disabled in a lot of production environments for this reason.

But if you explicitly handle exceptions using IF statements then that's overhead too, right?

yes but i think branch prediction essentialy makes them zero overhead

Re: Async/Await is finally back in Zig

#59

All the stunts in async/await or goroutines in go stem from the fact that there is no support for something lighter than posix threads in kernel. Shouldn't the OS kernel innovate in this area instead of different languages in userland attempting to solve it?

Fair. The languages have to come up with something based on APIs that were not meant for that, like io_uring, etc.

Re: Async/Await is finally back in Zig

#60
post #7

Earlier quoted context omitted.

I really wish people would get over the coloring meme. Knowing if a function will yield the thread is actually extremely relevant knowledge you want available.

What bothers me, for example in Python, with the function coloring is that it creeps everywhere and you need to rewrite your functions to accommodate async. I think being able to take and return futures or promises and handle them how you wish is better ergonomics.

> I think being able to take and return futures or promises and handle them how you wish is better ergonomics.

You can do that. If you don't await an async call, you have a future object that you can handle however you want.

Post reply on HN