Subject: [clisp-list] buffering and partial read/writes (was: socket-streams vs. two-wa y streams)

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Thu Feb 14 07:58:13 2002

Todd Sabin wrote:
>Anyway, food for thought.  With these changes, my web proxy gets the
>same throughput for large downloads as I get with the C proxy I have
>been using, ~190K/s.  I.e. the limiting factor is my bandwidth.  When
>I have to use unbuffered sockets, the best it could do was ~30K/s.

Do you think READ/WRITE-SOME (see below) would be enough for your task?

  > > it's totally impossible to read a client's requests unless they happen
  > > to terminate on 4K boundaries (or the client closes his end of the
  > > socket with shutdown(2) before receiving a reply).
>   The other
>piece needed for this is to change full_read in unixaux.d to return
>less than 4096 bytes of data if possible.  (Other _read functions
>would need to be similarly modified.)  With those changes buffered
>sockets are quite usable, though the hang problem still exists.

full_read() ought to maintain the invariant that its name claims.

In my ancient CLISP-TODO file I have a notice about implementing something I choose to name READ-SOME[-BYTES/SEQUENCE] and its WRITE- equivalent. I think I never did it, or possibly only experimentally for Amiga-CLISP and not in mainstream.

Rationale: to put the programmer at equal with the C/python/perl etc. guys who can read or write *as much as is currently available* using read(), or write as much as fits in one go. This gives buffered-style performance-enhanced i/o for interactive streams (sockets and non-file-i/o are to be supported) at a very low implementation cost for CLISP.

Adding this may be an easy fix to a couple of problems whose "better" 100% solution is seemingly not agreed upon or completely thought out yet(?).

I just discovered while reading about simple streams that Allegro has:

REAd-SEQUENCE sequence stream &key start end PARTIAL-FILL
>Note that Allegro CL uses the additional partial-fill
>keyword argument, which is not specified in ANSI CL. 
http://www.franz.com/support/documentation/6.1/doc/streams.htm

So maybe an extra name like READ-SOME is unneeded and READ-SEQUENCE could be enhanced instead with :PARTIAL-FILL, introducing portability with AllegroCL.

Writing: the number of characters written must be returned. They define GET-SOME-RAW-DATA in their base64 example though. Simple-streams documents WRITE-VECTOR, which has interesting behaviour I never thought about (blocking for first character, non-blocking afterwards), whereas my thoughts went along their WRITE-BYTES (device level, pass through to write()).
http://www.franz.com/support/documentation/6.1/doc/pages/operators/excl/write-vector.htm
So maybe CLISP may as well introduce another name.

I didn't think about interaction of this partial stuff with variable-size stream-element types (idea predates their implementation).

Sam>BTW, what is this 4096 world constant?

IIRC Bruno and I introduced the 4KB buffering size many years ago, after some benchmarking of mine showing that 4KB was an excellent compromise. Larger buffers did not noticably speed up execution, smaller ones (like 512 bytes) were noticably slower.

Regards,
	Jörg Höhle.

---

From: Todd Sabin <[email-masked]>
Date: Thu Feb 14 18:24:02 2002

> Do you think READ/WRITE-SOME (see below) would be enough for your task?

Probably, though what I've already done is necessary for providing
that, I think.

> full_read() ought to maintain the invariant that its name claims.

If we're going to make it possible to read something other than a full
4K block, then we have to have a function to do it.  We could make a
partial_read, but it would just duplicate 99% of full_read, so it
doesn't seem worth it.  I guess we could change the name of full_read
to full_or_partial_read or read_some or something else..

> In my ancient CLISP-TODO file I have a notice about implementing
> something I choose to name READ-SOME[-BYTES/SEQUENCE] and its WRITE-
> equivalent. I think I never did it, or possibly only experimentally
> for Amiga-CLISP and not in mainstream.
> 
> Rationale: to put the programmer at equal with the C/python/perl
> etc. guys who can read or write *as much as is currently available*
> using read(), or write as much as fits in one go. This gives
> buffered-style performance-enhanced i/o for interactive streams
> (sockets and non-file-i/o are to be supported) at a very low
> implementation cost for CLISP.
> 
> Adding this may be an easy fix to a couple of problems whose
> "better" 100% solution is seemingly not agreed upon or completely
> thought out yet(?).

I was thinking that adding read-sequence and write-sequence ala
Allegro would be nice, too.  But the patch I sent is a necessary first
step, AFAICT.  And it doesn't (or shouldn't) change the semantics of
any user visible behavior, aside from making some calls return sooner
than they otherwise would have.

Todd