[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

A few random I/O proposals



   Date: Fri, 05 Jun 92 17:58:23 -0400
   From: david carlton <carlton@husc.harvard.edu>

   On Sun, 31 May 92 22:11:01 -0400, "Aubrey Jaffer" <jaffer@martigny.ai.mit.edu> said:
   >> Date: Sat, 30 May 92 12:31:05 -0400
   >> From: david carlton <carlton@husc.harvard.edu>

   >> With terminals, there is essentially no loss from not buffering
   >> output, since programs can generate unbuffered output faster than
   >> humans or terminals can handle.

   > You have this backwards.  There would be a very large performance
   > impact because you would be requiring your process to be running to
   > send each character.  Each character write would cause your process to
   > be swapped out if there were another process to run.  This would limit
   > you to about 60 cps on many systems.  This is below the 100 cps of a
   > 9600 buad line (which can easily be acheived with buffering).

   I don't understand this paragraph.  It seems to me that the main extra
   overhead from unbuffered output is that you would have to do a system
   call on each character that you output, and system calls are
   relatively slow.  But do they normally make it more likely that your
   process be swapped out as well?  (More likely compared to if you were
   taking the same amount of time as you did with unbuffered output, just
   not doing any system calls.)  I just ran a simple test case of a pair
   of programs one of which looped and did nothing (to make sure that
   there was always another process waiting to run) and the other of
   which wrote characters to my xterm, flushing after each character, and
   the latter program wrote about a (24x80) screenful of text a second,
   which is plenty fast enough for screen output for me and a lot faster
   than the figures that you come up with.  But I don't claim to know
   much about the intricacies of UNIX (or other operating systems')
   process management, so maybe I am missing something.

Your original message said:

   Date: Sat, 30 May 92 12:31:05 -0400
   From: david carlton <carlton@husc.harvard.edu>

   I don't like this so much.  The ideal way that output should work is
   for it to be unbuffered - buffering is really just a performance hack
   adopted out of necessity.  Given that, I think that implementations...

To which I tried to explain that truly unbuffered serial output is not
available and not practical on multitasking operating systems.  The
slowdown comes not from the system call overhead (although that
contributes a second order effect) but from having to wait for
physical transmission of the character, during which time your process
can be suspended.  This phenomena occurs not on fast channels like the
Xterminal you used, but on slow ones like serial modem lines.

Furthermore, your unix machine buffers the output for you; I know
because I have written Unix serial device drivers.

   I am aware that there are other ways to get the desired effect.  I
   just think that they are a real pain.  I think you need more than just
   fflush, however - typically I don't care whether or not output is
   buffered if it is going to a file, for example, so I would only want
   to flush output if I am not writing to a file.

But I do need to be able to control when output goes to a file.  There
might be other readers of the file I am writing or I may need to
assure that a file (B-trees, for instance) is in a consistent state.

   And so forth and so
   on.  I would far prefer to have the Scheme implementation to do a good
   guess for me as to whether or not I care about seeing the output
   immediately, leaning towards the "I care" side, and avoid me all of
   that trouble.

There seem to be several options:

<1> specify nothing.

<2> have FORCE-OUTPUT procedure.

<3> have output flushed every second.

<4> have output flushed every character.  Have no local buffering.

<5> have output flushed on ttys when corresponding channel is read.

There have been further variations on these involving determining
whether a particular port "is a tty".  Although there is a POSIX call
for this, it is not very meaningful because pseudo-ttys and pipes are
used for the same purposes.  Also, as I pointed out above, there are
uses for flushing output to a file.

Whether (NEWLINE) should flush its port is a separate issue.

Looking at the options in detail:

<1> specify nothing.

This leaves unspecified when the side effects from output operations
take effect.  Although there is a procedure (INPUT-READY?) for
determining time dependent behavior of input, there is no
corresponding procedure for specifying time dependent behavior of
output.

<2> have FORCE-OUTPUT procedure.

Common Lisp has this function.  Some complained that it was difficult
to use FORCE-OUTPUT correctly.  I point out that the symmetric case of
INPUT-READY? has the same problem: If you forget to use it, your
process will hang until input is ready.

<3> have output flushed every second.

This doesn't do much to alleviate uncertainty in timing (unless time
functions are also present).  In order to assure that output has been
written, Scheme will need to wait. This interval, or even a tenth of
it, can be an eternity to wait on a supercomputer.

<4> have output flushed every character.  Have no local buffering.

This would make the behavior of Scheme mirror the underlying operating
system.  On microproccessors, that could mean losing characters on
input and Scheme would do no other computation until output was sent.
This has a performance penalty due to system calls for every WRITE.

<5> have output flushed on ttys when corresponding input channel is
read.

This covers only the use of FORCE-OUTPUT when displaying prompts.
Finding the corresponding input channel may not be meaningful on
window systems.  It doesn't provide a way to synchronize output to
pipes or files.