[openfirmware] r934 - forth/kernel

svn at openfirmware.info svn at openfirmware.info
Sat Sep 13 00:27:47 CEST 2008


Author: wmb
Date: 2008-09-13 00:27:47 +0200 (Sat, 13 Sep 2008)
New Revision: 934

Modified:
   forth/kernel/kernel.fth
Log:
OLPC trac 8139 - Performance improvement in deblocker - don't read
data into buffer if the data is going to be overwritten.




Modified: forth/kernel/kernel.fth
===================================================================
--- forth/kernel/kernel.fth	2008-09-12 22:23:45 UTC (rev 933)
+++ forth/kernel/kernel.fth	2008-09-12 22:27:47 UTC (rev 934)
@@ -2061,13 +2061,16 @@
    then
 ;
 
+: align-byte#  ( d.byte# -- d.aln-byte# )  fid @ alignop @ execute  ;
+: byte#-aligned?  ( d.byte# -- flag )  2dup align-byte#  d=  ;
+
 \ An implementation factor which
 \ fills the buffer with a block from the current file.  The block will
 \ be chosen so that the file address "d.byte#" is somewhere within that
 \ block.
 
 : fillbuf  ( d.byte# -- )
-   fid @ alignop @ execute  ( d.byte# ) \ Aligns position to a buffer boundary
+   align-byte#              ( d.byte# ) \ Aligns position to a buffer boundary
    2dup fstart 2!           ( d.byte# )
    fid @ seekop @ execute               ( )
    bfbase @   bflimit @ over -          ( adr #bytes-to-read )
@@ -2080,8 +2083,40 @@
 \ returns the address within the buffer corresponding to the
 \ selected position "d.byte#" within the current file.
 
+: bufaddr>  ( bufaddr -- d.byte# )  bfbase @ - s>d  fstart 2@ d+  ;
 : >bufaddr  ( d.byte# -- bufaddr )  fstart 2@ d- drop  bfbase @ +  ;
 
+\ This is called from fputs to open up space in the buffer for block-sized
+\ chunks, avoiding prefills that would be completely overwritten.
+: prefill?  ( endaddr curaddr -- endaddr curraddr flag )
+
+   \ If the current buffer pointer is not block-aligned, must prefill
+   bfcurrent @  bufaddr>  byte#-aligned?  0=  if  true  exit  then  ( end curr )
+
+   2dup -  0 align-byte# drop           ( end curr aln-size )
+
+   \ If the incoming data won't fill a block, must prefill
+   ?dup  0=  if  true exit  then        ( end curr aln-size )
+
+   \ If there is still space in the buffer, just open it up for copyin
+   bflimit @ bfend @ -  ?dup  if        ( end curr aln-len buffer-avail )
+      min  bfend +!  false exit
+   then                                 ( end curr aln-len )
+
+   \ Save current on stack because ?flushbuf clears it
+   bfcurrent @                          ( end curr aln-len current )
+
+   \ The buffer is full; clear out its old contents
+   ?flushbuf                            ( end curr aln-len )
+
+   \ Advance the file pointer to the new buffer starting position
+   bufaddr> fstart 2!                   ( end curr aln-len )
+
+   bfbase @ + bflimit @ umin  bfend !   ( end curr )  \ Room for new bytes
+   bfbase @  dup bftop !  bfcurrent !   ( end curr )  \ No valid bytes yet
+   false
+;
+
 \ An implementation factor which
 \ advances to the next block in the file.  This is used when accesses
 \ to the file are sequential (the most common case).
@@ -2352,8 +2387,16 @@
    over bfend @ bfbase @ -  u>= or  if ( d.byte# offset )
       \ Not in buffer
       \ Flush the buffer and get the one containing the desired byte.
-      drop ?flushbuf 2dup fillbuf      ( d.byte# )
-      >bufaddr                         ( bufaddr )
+      drop ?flushbuf                         ( d.byte# )
+      2dup byte#-aligned?  if                ( d.byte# )
+         \ If the new offset is on a block boundary, don't read yet,
+         \ because the next op could be a large write that fills the buffer.
+         fstart 2!                           ( )
+         bfbase @  dup bftop !  dup bfend !  ( bufaddr )
+      else
+         2dup fillbuf                        ( d.byte# )
+         >bufaddr                            ( bufaddr )
+      then                                   ( bufaddr )
    else
       \ The desired byte is already in the buffer.
       nip nip  bfbase @ +           ( bufaddr )
@@ -2429,13 +2472,14 @@
 \ Writes count bytes from memory starting at "adr" to the current file
 : fputs  ( adr count fd -- )
    file @ >r  file !
-   over + swap  ( endaddr startaddr )
-   begin  copyin  2dup u>
-   while
-      \ Here there should be some code to see if there are enough remaining
-      \ bytes in the request to justify bypassing the file buffer and writing
-      \ directly from the user's buffer.  'Enough' = more than one file buffer
-      sync  bfcurrent @ shortseek ( endaddr curraddr )
+   over + swap                    ( endaddr startaddr )
+   begin  copyin  2dup u>  while  ( endaddr curraddr )
+      sync                        ( endaddr curraddr )
+      \ Prefill? tries to avoid unnecessary reads by opening up space
+      \ in the buffer for chunks that will completely fill a block.
+      prefill?  if                ( endaddr curraddr )
+         bfcurrent @ shortseek    ( endaddr curraddr )
+      then
    repeat
    2drop
    r> file !




More information about the openfirmware mailing list