At Wed, 16 Jun 2021 17:33:56 -0400, George Neuner wrote:
> On 6/16/2021 3:45 PM, Matthew Flatt wrote:
> > At Wed, 16 Jun 2021 14:25:40 -0400, George Neuner wrote:
> > > It looks like the problem 
> > > is that "flush" is not defined ...
> >
> > Yes, "returns without blocking after writing as many bytes as it can
> > immediately flush" is vague, and more or less intentionally so. The
> > intent it really "writes as much as is convenient, with the guarantee
> > that anything written is completely flushed". Maybe the documentation
> > should be revised to say something more like that.
> >
> > There's not intended to be a guarantee that as much is written as could
> > possibly make sense by `write-bytes-avail`. Implementation issues may
> > make writing additional bytes inconvenient enough that it doesn't
> > happen, for example, even if more is always written on the next
> > `write-bytes-avail*` call. Also, ports are meant to be used in
> > concurrent settings where the notion "as much as possible" is prone to
> > race conditions.
> 
> Dumb question ... why should non-blocking I/O worry about "flush" at 
> all.  Why not behave like native I/O where writes are guaranteed only to 
> get to the I/O buffer?

If I understand what you mean, then that's the intent. But I think
you're using "buffer" in the sense of the OS layer. That's different
than the buffer that you have in, say, the C library. The Racket port
model uses "buffer" to mean the one like the one implemented in a C
library, and "flush" is used also used in the C library sense, and not
in terms of a buffer that might exist in the next layer (which might be
the OS or might not).

> > So, the intent is that you use `write-bytes` when you want to wait
> > until all bytes are written (maybe because you know that will be soon
> > enough, for whatever reason). But when using `write-bytes-avail`, be
> > prepared for a fraction of the bytes to be written, for whatever
> > reason.
> 
> It is not a problem, per se, but it is an issue that with a long string, 
> you may be forced to call  write-bytes-avail  multiple times just to be 
> filling up the port buffer.  That seems very inefficient and is at odds 
> with how native non-blocking I/O calls behave (completing or filling the 
> buffer before returning).

Probably this became more clear with experiments that Shu-Hung and you
reported, but that's what happens, except that trying to write to a
pipe whose buffer is full will then grow the buffer. Naturally, the
buffer grows by doubling --- up to the pipe's capacity limit, if any.

An OS pipe tends to have a fixed size (OS-level) buffer that is
allocated up front, and that serves as both the maximum granularity of
writes and the capacity of the pipe. Racket pipes are meant to work in
those kinds of cases, but also adapt to cases where pipes are small and
numerous or where they have no capacity limit, so the write granularity
and capacity are not so tightly coupled.

There's likely room for improvement. Racket BC pipes absorb more in a
non-blocking write, because MzScheme was very slow in the old days, and
it was worth looping and trying harder in the low layers instead of
having to go back out to slow MzScheme code. For Racket CS, that
slow--fast boundary isn't there, and so the lower layer core tries to
stay as fast as possible by branching and looping less internally, but
I don't really know if that's the best choice.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/20210617170850.17e%40sirmail.smtps.cs.utah.edu.

Reply via email to