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.