> I think Bruno tested that 10+ years ago.
> It might be different now.
It's most certainly still the same: When you have to process N
entities in two or more places A, B, ..., it is always faster to
process the N entities at A, then all at B, then all at C, etc.,
than to process one entity at A, then at B, then at C, ..., then
turn back to A, process the second entity, process it at B, then at
C, then for the third entity, and so on.
Here the entities are bytes, A is clisp, and B is the kernel.
The reason is that without buffering, you have many more context
switches (these include function calls or system calls). Whereas
with buffering, there are not only less function calls, but also
most of what a CPU fetches from memory comes from the L1 cache of
This argument makes sense if
- you're doing IO in lisp one byte at a time
- the call to the kernel from lisp does that IO one byte at a time.
As for the first point, if I use ext:read/write-byte-sequence then
this argument seems not to apply at all on input. For output, I'd
guess that calling write-byte-sequence unbuffered would have an OS
overhead similar to calling it buffered and then doing force-output.
I see a few other possible issues of less importance, such as whether
the sizes of the buffers cause communication to stop unnecessarily
while you're computing, and the time and space used copying data.
On the second point, it appears possible to read a single byte from a
socket. Is this what read-byte does for unbuffered streams?
In stream.d it looks like make_socket_stream is setting
TheStream(stream)->strm_rd_by = P(rd_by_twoway);
regardless of whether the stream is buffered.
And it looks to me like even for unbuffered reads you might as well
get whatever you're going to have to get anyway - whatever is in the
current packet or disk block, etc. In essence, I'm imagining that
socket stream read does a certain amount of buffering even for
unbuffered streams, so the performance difference should be small.
On the output side, my model is that an unbuffered write is more or
less the same as a buffered write followed by force-output. So if
you were going to do (loop ... write-byte ... finally force-output)
then it would be better to use a buffered stream.