Live data from Hacker News

Zig's New Async I/O

kristoff.it

251–260 of 293 posts

Re: Zig's New Async I/O

#251
post #207

Earlier quoted context omitted.

Async/await tend to be IO bound, in zigs case hiw can i know what to use and when? Say i do a db call, thats clearly IO, and later do heavy CPU thing, now how do i know that the CPU thing does not block inside my async io thing? I guess its pure luck if the io implementation can handle both, but who knows?

> how do i know that the CPU thing does not block inside my async io thing? I think it's common sense to not interweave IO with long-running CPU, hence sans IO. If you want to go that route, we already have solutions: goroutines and beam processes.

This was my point. With Go it does not matter, i can do IO or CPU both with Gos concurrency (CSP), but with async/await i usully cannot, i assume this is not something Zig is planning on, as it seems to be all about IO.

Re: Zig's New Async I/O

#252
post #185
post #166

Earlier quoted context omitted.

> Well, no. In zig that's `const x = foo(io)`. If `foo` needs to do IO, sure. Or, more typically (as I mentioned in a different comment), it's something like `const x = something.foo()`, and `foo` can get its `Io` instance from `something` (in the Zig compiler this would be a `Compilation` or a `Zcu` or a `Sema` or something like that). > Using stackless coroutines and green threads results in a completely different…

Also, I do find it funny that we went from "Zig has completely defeated function coloring" to "Zig has colored objects".

but that's not even the case, because it's certainly possible to write a function that receives an object that holds onto an io (and uses it in its vtable calls) that equally well receives an object that doesn't have anything to do with io [0]. The consumers of those objects don't have to care, so there's no coloring.

[0] and this isn't even really a theoretical matter, having colorblind object passing is extremely useful for say, mocking. Oh, I have a database lookup/remote API call, which obviously requires io, but i want fast tests and I can mock it with an object with preseeded values/expects -- hey, that doesn't require IO.

Re: Zig's New Async I/O

#253
post #234

Earlier quoted context omitted.

> no good reason to have more than one event loop Per thread—once you start working in multiple threads you have the choice to have one global event loop, which comes at the cost of all async code being effectively serialized as far as threads are concerned*, or one event loop per thread. * Which can be fine if your program is mostly not async but you have that one stubborn library. Yay async virality.

I can't say there's no good reason to have per thread event loops, but I think I can say if you do know of one you're suffering a terrible curse. I can only imagine the constraints that would force me to do this.

Because you have a main application running a web server and a daemon worker thread performing potentially long running tasks that use async libraries and you don't want to block the responsiveness of your web server. It's really not that bad, at least in Python.

Re: Zig's New Async I/O

#254
post #253

Earlier quoted context omitted.

I can't say there's no good reason to have per thread event loops, but I think I can say if you do know of one you're suffering a terrible curse. I can only imagine the constraints that would force me to do this.

Because you have a main application running a web server and a daemon worker thread performing potentially long running tasks that use async libraries and you don't want to block the responsiveness of your web server. It's really not that bad, at least in Python.

Well, here we go I guess. Why can't you just use FastAPI? Or Tornado? Isn't there also an async Flask? Isn't Django also async now? What minor god have you angered to be chained to a non-async framework?

Re: Zig's New Async I/O

#256

Earlier quoted context omitted.

> a change in a leaf function in a little file in a random helper module could introduce asynchronocity which propagates all the way up to your `pub fn main` If this doesn't make the argument that Zig has certainly not defeated function coloring, I don't know what would. The fact that this change to how my program runs is hidden away in the compiler instead of somewhere visible is not an improvement.

> If this doesn't make the argument that Zig has certainly not defeated function coloring, I don't know what would. if you're opting into stackless coroutines then yeah you're opting into their viral nature, but the point is that you don't have to . as the application author your dependencies won't opt you forcefully in using stackless coroutines (or any singular execution model), which is currently the case with oth…

Small marketing suggestion: maybe "limit function coloring" instead of "defeat function coloring". I like Zig's approach so far, but clearer terms would help avoid pointless arguments and disappointments that a certain proglang supremacist community loves.

Re: Zig's New Async I/O

#257
post #224

Note that this same concept is "sans io" and was previously discussed for it's use in Rust: https://www.firezone.dev/blog/sans-io https://sans-io.readthedocs.io/ https://news.ycombinator.com/item?id=40872020

If the functions are still calling I/O methods directly rather than the I/O being externally driven, I don't think that qualifies as sans-io, based on my previous exposure / based on your second link: > For byte-stream based protocols, the protocol implementation can use a single input buffer and a single output buffer. For input (that is, receiving data from the network), the calling code is responsible for deliveri…

Yep, that would be more like structured concurrency also mentioned in linked blog post. sans-io is about state machine as interface, but unfortunately does not specify a formal model or how to synthesize/derive one etc.

Re: Zig's New Async I/O

#258
post #29

Earlier quoted context omitted.

Here's a trick to make every function red (or blue? I'm colorblind, you decide): var io: std.Io = undefined; pub fn main() !void { var impl = ...; io = impl.io(); } Just put io in a global variable and you won't have to worry about coloring in your application. Are your functions blue, red or green now? Jokes aside, I agree that there's obviously a non-zero amount of friction to using the `Io` intreface, but it's som…

Well, it's not really a joke. That's a valid strategy that languages use. In Go, every function is "async". And it basically blocks you from doing FFI (or at least it used to?). I wonder if Zig will run into similar issues here. > 1. Code can't be reused because the async keyword statically colors a function This is fair. And it's also a real pain point with Rust. However, it's funny that the "What color is your func…

> And it basically blocks you from doing FFI

It doesn't block it. But it does make FFI much more expensive in go than in languages like Rust, because every foreign call needs to set up a c-compatible stack.

Re: Zig's New Async I/O

#259
post #253

Earlier quoted context omitted.

Because you have a main application running a web server and a daemon worker thread performing potentially long running tasks that use async libraries and you don't want to block the responsiveness of your web server. It's really not that bad, at least in Python.

Well, here we go I guess. Why can't you just use FastAPI? Or Tornado? Isn't there also an async Flask? Isn't Django also async now? What minor god have you angered to be chained to a non-async framework?

Of all the responses, this was perhaps my least expected one when I was talking about being chained to an async framework. Async isn't a replacement for threads, async doesn't let you spread your work out over multiple cores and doesn't give you time slicing. In Python the asyncio module actually gives you a threadpool to run computationally intensive work in as kind of one-offs. But when you need something like background job processing and want to also reap the benefits of asyncio, like being able to pull multiple tasks off the queue, and progress on others while a job does io, then you need an event loop in the other thread. It was specifically avoiding locking up FastAPI that lead me to use multiple event loops in the first place.

You're free to spin the job worker off to another process but however you swing it it's still multiple event loops you deal with. But with threads you get to only load your Python app into memory once.

Re: Zig's New Async I/O

#260
post #79

Earlier quoted context omitted.

> But I guess it's going to be 2 params from now on. >> So, if you discover that a code path you previously thought was pure actually does need to perform IO, then you don't need to apply some nasty viral change; you just grab `my_thing.io

Python, for example, will let you call async functions inside non-async functions, you just have to set up the event loop yourself. This isn't conceptually different than the Io thing here.

But the asyncio event loop is not reentrant, so your faux sync functions cannot be safely called from other async functions. It is an extremely leaky abstraction. This is not a theoretical possibility, I stumbled on the issue 15 minutes into my foray into asyncio (turns out that jupyter notebooks use asyncio internally).

There are ways around that (spawn a separate thread with a dedicated event loop, then block), or monkey patch asyncio, but they are all ugly.

Post reply on HN