Comment by giovannibajo1
3 years ago
I think also “least surprise” depends on your background. In Go, also files don’t buffer by default, contrary to many languages including C. If you call Write() 100 times, you run exactly 100 syscalls. Intermediate Go programmers learn this and that they must explicitly manage buffering (eg: via bufio).
I don’t think it’s wrong that sockets follow the same design. It gives me less surprise.
that Write() doesn't call fsync() though, does it?
so there's no buffering going on in the application, but the bytes almost certainly don't hit the disk before Write() returns
they've just been staged into an OS buffer, with the OS promising to write them out to the disk at a later time (probably, maybe...? hopefully!)
which is exactly the same as a regular TCP socket (with Nagle disabled, i.e. the default, non Go way)
For userland programming, what matters is the syscall level, as that is expensive (and also the API you have for the kernel). Whether the kernel then does internal buffering is irrelevant and uncontrollable beyond any other syscalls which may or may not be implemented (maybe you're running on a custom kernel that doesn't buffer disk writes?).
One write == one syscall, easy. If you want buffering, you add it.
> For userland programming, what matters is the syscall level, as that is expensive
which is why pretty much every programming language buffers file output by default
even C
(other than Go, obviously)
> Whether the kernel then does internal buffering is irrelevant
everyone that's attempted to write reliable software that cares about what ends up on disk, or the other side of the socket will disagree
I think my C is getting rusty, but "write" operates on a file descriptor, doesn't it? It's unbuffered. The buffered versions are things like printf and puts.
That's POSIX; C's equivalent is a FILE, which generally is buffered.
I thought Linux does in kernel buffering with `write`