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

Re: pipes & ptys



  > But if I open a pipe as a pseudo tty and use 1 Bytes reads/writes - which
  > looks normal for shell i/o to me
  
   hmm user processes doing 1 byte read()/write()s _is_ slow. :(  system
  calls are expensive...  (and also the library adds its share too...)

A simple shell would just use cooked mode and read a line at a time, not
single-character, btw...
  
   not sure how much can be done about 1-byte IO (i fear the library
  and system call overhead are the biggest part already...)  i think the
  first thing to do would be change gnulib and all your other programs
  that still do it to avoid 1-byte IO where possible. (might need a few
  if (__mint) and Fcntls on ttys but the result should be worth it...)
  and then improve tty.c&friends so that long read/writes can get _really_
  efficient.  currently the problem is they do a lot of device-level
  1-char IO and shuffling bytes into 32-bit `chars' and back... i.e. when a
  pty slave writes 1k that gets expanded into 4k, and when the master then
  does a 1k read its collapsed again.  and whats worse pipefs' read then
  gets called a 1000 times!  instead of once.  that is what makes ptys
  slow... (and serial ports too, but i said that before. :)

(Just a note to TeSche - the 1 byte I/Os are converted to 4 bytes to allow
pty's to pass scan code and shift status info, just like Bconin from console.)
  
   now how fix this (i mean _really_ fix this. so that a 1k read ends up
  as one 1k device read whenever possible, without additional moving data
  around) and stay compatible with existing devices?  here is an idea...
  
  1. add 2 optional functions to DEVDRV struct, for now i call them bread
  and bwrite. (NULL means they are not there)  they work like device read
  and write, only with bytes instead of longs.  (btw there are 3 longs
  reserved in DEVDRV now and i can think of atleast 2 more functions to
  add later, readv and writev...  so extend the struct somehow?)
  
  2. if bwrite is there use it instead of write in tty_write (also in
  bflush, midiws...), if the write is RAW just check for job control and
  return (*f->dev->bwrite)(f, buf, nbytes);
   and if bread is there do the same atleast for RAW reads in tty_read.
  (this includes reading pty masters...)
  
  3. add bread and bwrite functions to the pty device.  the slaves output
  pipe can then be changed to use bytes directly. (i think.  the other
  direction of course not...)
  
  4. add support for CLOCAL, HUPCL, VMIN etc and make _real_ modem devices...
  with bread/bwrite they finally could get decent thruput without 99% CPU load.

...and CTLECHO, I guess we want full termio(s) support, eh?
  
   this is just an idea i got and i have no idea if and when i could do
  all this... :)  but what do you think?

I kind of like it. The main point being, we want a system call that actually
reads or writes more than 1 byte at a time for ttys. So doing an Fread of 1K
on /dev/modem1 does a single call, not 1000 Bconin's... I would like to see
these new read and write functions replace Bconin/Bconout, with Bcon* just
being a special-case (single-character) of them.

I would suggest that a better way to handle this would be to continue
supporting the 4 bytes per character, but have an additional flag bit which
indicates whether or not the caller is interested in the 3 extra bytes. If not,
just perform the data copy by incrementing the pointer by 4 instead of by 1...