Earlier quoted context omitted.
> Arguably, our solution to the problem is just to color every function async-colored. This is essentially how Golang achived color-blindness.
It's basically how Java does it (circa 17) as well. It's something you really can't do without a pretty significant language runtime. You also really need people working within your runtime to prefer being in your runtime. Environments that do a lot of FFI don't work well with a colorblind runtime. That's because if the little C library you call does IO then you've got an incongruous interaction that you need to worr…
Zig's New Async I/O
261–270 of 293 posts
Re: Zig's New Async I/O
#262I feel that I have to point this out once again, because the article goes so far as to state that: > With this last improvement Zig has completely defeated function coloring. I disagree with this. Let's look at the 5 rules referenced in the famous "What color is your function?" article referenced here. > 1. Every function has a color Well, you don't have async/sync/red/blue anymore, but you now have IO and non-IO fun…
The key difference to typical async function coloring is that `Io` isn't something you need specifically for asynchronicity; it's something which (unless you make a point to reach into very low-level primitives) you will need in order to perform any IO, including reading a file, sleeping, getting the time, etc. It's also just a value which you can keep wherever you want, rather than a special attribute/property of a…
The innovation of async over threads is simply to allocate call stack frames on the heap, in linked lists or linked DAGs instead of fixed-size chunks. This sounds inefficient, and it is: indexing a fixed block of memory is much cheaper. It comes with many advantages as well: each "thread" only occupies the amount of memory it actually uses, so you can have a lot more of them; you can have non-linear graphs, like one function that calls two functions at the same time; and by reinventing threading from scratch you avoid a lot of thread-local overhead in libraries because they don't know about your new kind of threads yet. Because it's inefficient (and because for some reason we run the new threading system on top of the old threading system), it also became useful to run CPU-bound functions in the old kind of stack.
If you keep the linked heap activation records but don't colour functions, you might end up with Go, which already does this. Go can handle a large number of goroutines because they use linked activation records (but in chunks, so that not every function call allocates) and every Go function uses them so there is no colour.
You do lose advantages that are specific to coloured async - knowing that a context switch will not occur inside certain function calls.
As usual, we're beating rock with paper in the moment, declaring that paper is clearly the superior strategy, and missing the bigger picture.
Re: Zig's New Async I/O
#263Earlier quoted context omitted.
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 back…
Re: Zig's New Async I/O
#264Earlier quoted context omitted.
To me, there's no difference between the IO param and async/await. Adding either one causes it to not be callable from certain places. As for the second thing: You can do that, but... You can also do this in Rust. Yet nobody would say Rust has solved function coloring. Also, check this part of the article: > In the less common case when a program instantiates more than one Io implementation, virtual calls done throug…
>To me, there's no difference between the IO param and async/await. You can't pass around "async/await" as a value attached to another object. You can do that with the IO param. That is very different.
In other words, you don't need such an Io object upfront: You need it when you want to actually drive its execution and get the result. From this perspective, the Zig approach is actually less flexible than Rust.
[0]: https://docs.rs/tokio/latest/tokio/runtime/struct.Handle.htm...
Re: Zig's New Async I/O
#265Earlier quoted context omitted.
The problem is that C expects to have enough stack to put stuff there, but green threads allocate small stacks to reduce (virtual) memory use.
That’s not a problem when a dedicated thread pool is used as mentioned by GP. However they don’t solve the thread affinity issue.
Re: Zig's New Async I/O
#266Note 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…
I guess a better name for this approach might be "explicitly managed I/O".
Re: Zig's New Async I/O
#267If you are using I/O with green threads but sleep the OS thread, you block other green threads. Likewise, if you have stackless coroutines (when they exist in Zig) but sleep the OS thread, you block other coroutines.
So is there an io.sleep?
Also - does any of this use io_uring on Linux?
Re: Zig's New Async I/O
#268Earlier quoted context omitted.
Passing in your dependencies as function arguments is a form of dependency injection. It is the simplest and thus arguably best form of dependency injection.
This is like saying arithmetic is a form of calculus, the simplest form. Ie it reduces the concept (DI) to a meaningless tautology.
Re: Zig's New Async I/O
#269Earlier quoted context omitted.
That’s not a problem when a dedicated thread pool is used as mentioned by GP. However they don’t solve the thread affinity issue.
That's the reason for the thread pool, and the resulting thread affinity issue.
Re: Zig's New Async I/O
#270Earlier quoted context omitted.
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 u…
If I call `a.foo()` but `a` has and is using a stackless coroutine IO but the caller is being executed from a green thread IO then as was said before, I'm hitting UB.
But, I do like that you could skip/mock IO for instance. That's pretty neat.