[net.micro.amiga] File random access times.

ali@navajo.STANFORD.EDU (Ali Ozer) (08/27/86)

[]

Using the Manx compiler, version 3.20a, I did some timings on random
file accesses. Here are some of the interesting results:

(The file was 128 kilobytes long. The sequence was repeated 10 times, and the
 results given are the total time for the 10 iterations. 1.1 and 1.2 refer
 to the versions of Kickstart/Workbench used. (1.2 was beta 6.) "Buf" means
 buffered I/O (using fopen, fseek, fread), "Unbuf" unbuffered I/O (using
 open, lseek, and read). After every seek, the indicated number of characters
 were read from the file. The timings to do not include the time to open and
 close the files.)

   Sequence of seeks (ie,    Number of 
   locations accessed)       chars read    Buf1.1  Unbuf1.1  Buf1.2  Unbuf1.2
   --------------------------------------------------------------------------
1. 0                                 0       0.4       0.3     0.4       0.3
                                     1       5.2       0.0     5.2       0.0
                                    10       5.5       0.0     5.5       0.0
                                  1000       6.1       5.2     6.1       5.2
   ---------------------------------------------------------------------------
2. 60000                             0       1.2       0.9     0.7       0.3
                                     1      14.0       0.2     5.7       0.0
                                    10      14.9       0.2     6.0       0.0
                                  1000      15.5      13.7     6.6       0.3
   ---------------------------------------------------------------------------
3. 120000                            0       1.6       1.0     0.8       0.4
                                     1      11.9       0.4     0.2       0.1
                                    10      12.8       0.4     0.2       0.1
                                  1000      13.4      11.9     0.8       0.2
   ---------------------------------------------------------------------------
4. 0, 1000, 2000                     0       1.1       1.1     8.8       8.7
                                     1       8.9       0.2     9.0       8.8
                                    10       9.1       0.2     9.0       8.8
                                  1000      11.0       8.8    10.9       9.1
   ---------------------------------------------------------------------------
5. 120000, 121000, 122000            0       3.5      25.6     1.2       0.7
                                     1      31.4      26.0     0.8       0.4
                                    10      32.4      26.0     0.8       0.4
                                  1000      34.2      26.2     2.6       0.8
   ---------------------------------------------------------------------------
6. 0, 10000, 20000                   0       1.1       1.2     9.1       9.1
                                     1      11.9       0.2    12.1       9.1
                                    10      12.2       0.3    12.1       9.1
                                  1000      14.0      11.9    14.0      12.2
   ---------------------------------------------------------------------------
7. 100000, 110000, 120000            0       8.8       8.9     9.5       9.6
                                     1      41.0       7.3    12.5       9.3
                                    10      42.6       7.3    12.5       9.2
                                  1000      44.4      38.1    14.3       9.7
   ---------------------------------------------------------------------------

From the above results, it seems like 1.2's seek functions are much more 
uniform across the file, meaning it takes about the same time to access
location 0 vs. location 100000, as rows labelled "6." and "7." show. But,
take a look at rows "4." and "5.". Accessing locations around 120000
is much faster than accessing locations around 0... In fact, 1.1 is faster
in accessing locations 0, 1000, 2000, while 1.2 is faster accessing locations
120000, 121000, 122000...  Seems pretty random (although I do get the same 
results over and over.)

In almost all cases, using unbuffered I/O seems to be faster. Even for purely
sequential reading (results not posted above), it seems like if call
read() with character count of 1000 or so, unbuffered I/O is faster
(I guess in this case it becomes equivalent to doing your own buffering.)

One final confusion in the above table is what happens if you read zero
characters. As rows "1.", "2.", and "3." show, sometimes reading zero
characters results in worse performance than reading 1 or even 10...
(more in the unbuffered case than in the buffered case).  Thinking maybe
read() is screwing up and actually reading some characters, I put an "if"
to prevent the call to read in cases where the number of chars was 0. Still,
I get the same results! The psuedo code is simply...

    get current tick
    do 10 times
      do the seek, complain if unsuccessful
      if (# of chars to read != 0) read, complaining if unsuccessful 
    get current tick, print time difference

I don't understand at all why reading NO characters should take more time than
actually reading characters...  I'll be happy to post the code I used, if
anyone is interested, but seems like I'm doing the right thing. Any ideas?

Of course, I guess there would be faster ways of doing disk I/O, with low
level Dos functions (which I haven't learned about yet --- there's so much to
read, so much to learn...). I would be 
interested in seeing what people have to say about the fastest way of reading
random sizes of data (say 0-1k) in from random locations in a 
large (>100k) file is...

Ali Ozer, Ali@Score.stanford.edu

dillon@CORY.BERKELEY.EDU (Matt Dillon) (08/28/86)

>Using the Manx compiler, version 3.20a, I did some timings on random
>file accesses. Here are some of the interesting results:

	Interesting results.   I would like to comment on your comment on
buffered I/O speeds (and buffered I/O in general, this isn't a flame or
anything).

>it seems like if call
>read() with character count of 1000 or so, unbuffered I/O is faster
>(I guess in this case it becomes equivalent to doing your own buffering.)

	My comment is that buffered I/O is useful when you are reading a lot
of junk in small segments.  For instance, try reading 8K one character at a 
time.  With unbuffered I/O, things go slowly.  With buffered I/O, reading is
an order of magnitude faster.  Additionaly, if you are making small relative
seeks, buffered I/O wins because most of the time the data is already in
the buffer and it doesn't have to make a system call.

	There is another use for buffered I/O:  Think of the situation 
where you are reading files and writing files on the same disk.  If you use
unbuffered I/O, the poor disk is continuously seeking between the track it's
reading and the track it's writing (because the sector cache is NOT a track
cache).  However, if you use buffered I/O with, say, a 4K input buffer and
a 32K output buffer, disk seeks are lessed and overall program speed 
increases by an order of magnitude.

	Finally, due to the bug in the RAM: disk, you always want to use
buffered output when writing to RAM: files.  If you write in smaller segments
to the RAM: disk, an incredible amount of memory is wasted for some reason.

					-Matt

rokicki@navajo.STANFORD.EDU (Tomas Rokicki) (08/31/86)

In article <8608281956.AA19132@cory.Berkeley.EDU>, dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
>             . . .  Additionaly, if you are making small relative
> seeks, buffered I/O wins because most of the time the data is already in
> the buffer and it doesn't have to make a system call.

It would be nice if this were true; unfortunately, the fseek() call in
the Manx library doesn't seem to have been written with this in mind.
I had to rewrite fseek() it for a few programs I have to make things
reasonably fast.  (fwrite() and fread() also have a bug and require
rewriting.)

Does anyone have any explanation for the random inconsistencies in the
data Ali Ozer presented on access times?  Things are wierd, there.

Also, I want a hard drive with fast transfer rates!  When loading an
executable of > 100K (as a lot of Amiga executables are), that five
to ten second delay can be very annoying.  Any pointers?

-tom