State of networking in `std.Io`

I’ve been writing about this in the past, but after the 0.16 release, things already got worse. The interface is missing several key features, that people are hacking around, tying to a particular std.Io implementation, so even if the library accepts io parameter, it doesn’t mean it will work with any std.Io implementation.

  1. Ability to configure socket options like keepalive, nodelay, etc.

  2. Ability to have read/write timeouts

  3. Ability to run poll as an operation

I have several open PRs for improving networking in std.Io, plus others waiting to get the initial ones merged, since they are stacked, but it seems that networking is not a priority. I realize that reviewing is hard and there are limited resources, I’m not trying to push, I’m just trying to understand the goal/priorities.

I guess I’m just trying to decide whether to invest further into networking libraries based on std.Io, or I give up and use my own networking APIs for now.

17 Likes

Let’s not do this in this thread, please. I like std.Io, it solves a real problem, it’s the first language outside of Go that can have networking libraries working on any backend. Let’s not make this into a wider topic. I just want to see if fixing networking in std.Io is a priority or not. And I mean just the interface layer, I personally don’t really care about any of the implementations in stdlib.

9 Likes

I have been working on a PR for a type safe setsockopt wrapper that (IMO) is a bit more zig like. Can you share links to your networking PRs? I would like to look them over. It would help focus the discussion too.

Speaking generally, I think the state of PRs is a problem, and Andrew has acknowledged this in the past. I don’t necessarily think your experience is Io/networking related, and might just be PR related.

I can’t personally be mad because reviewing PRs is a bit of a chore and always less fun than implementing something yourself. It can be demotivating for PR authors though.

2 Likes

Not just mine, but here is a list of important PRs:

Plus, there is a buch of open PRs for unix sockets / UDP, which I don’t care that much about, so I’ll not look for them.

3 Likes

I faced this very same thing building an epoll based TCP server. To set NONBLOCK on the socket I had to resort to direct std.os.linux.accept4, bypassing Io entirely.
The code ends up being a mix of Io and direct syscall using .socket.handle, which doesn’t particularly bother me, but perhaps defeats the purpose of Io, at least partially.

Truth be told, I don’t think I’m running into murky waters here as long as everything is single-thread, but as soon as I cross that line the mixed use of Io and lower level primitives might bite me back. Another aspect of this is that I’m intentionally not writing portable code, but instead linux targeted specifically, which maybe also defeats the purpose of or need for Io in this context (single threaded, single target :person_shrugging:).

But I guess the bottom line is: not having everything in the Io interface hasn’t stopped me from achieving what I wanted, just made a few select parts of the code non-portable and potentially non thread safe, which are compromises I can live with for now.

That’s the anti-pattern, which is acceptable in an application, but not in libraries. Currently, most libraries assume std.Io.Threaded, so they call syscalls like this, even blocking ones, like poll. Which in turns means I can’t use them with my own implementation of std.Io, at which point I just want to give up and use zio APIs exclusively, essentially building my own stack fully, ignore std.Io. But I feel that very little is missing to actually avoid these hacks and have cross-backend libraries, it just needs some dedication to bring featues into std.Io.

6 Likes

imo, don’t give up :slight_smile: i think it’s gonna just be a good bit slower than we want for now.

2 Likes

A couple of issues which I’ve run into recently while working on zigmirror:

  • Lack of ability to specify timeouts in a lot of places, which you’ve already mentioned. Working around this with std.Io.Select and a separate watchdog task works, but in a lot of cases it’s inefficient and tends to make the code rather messy
  • Inability to open a dgram unix socket to implement sd_notify without linking libsystemd
  • Lack of sendfile support for std.Io.net.Stream.Writer (though it looks like there’s been some progress on this recently thanks to you)

But overall I’ve enjoyed the experience of building a server on top of std.Io. Being able to write everything once and have it just work reasonably efficiently, regardless of what OS or event loop you run want to run it on, is super nice.

2 Likes

Good reminder, now that it’s merged, I could implement the blocking sendfile for std.Io.Threaded as I am curious how it compares to my zio user-mode implementation, which is currently much faster than the fallback used in std.Io.Writer.

3 Likes

I appreciate you bringing this up. I don’t personally have time to give these issues the amount of attention to detail that I think they deserve for a couple more weeks. Other team members may have time, it’s up to them. But at that point let’s strategize about releases. Maybe we tag 0.17.0 without solving these problems, but we try to do another “short” cycle (at least by intention) that aims only to address std.Io networking before the next tag.

17 Likes