Sub-optimal libc's read-ahead buffering behaviour

Maxim Sobolev sobomax at portaone.com
Wed Aug 3 16:32:44 GMT 2005


Checking the actual code confirm your point, thank you! However, I think 
that the current behaviour is at best inconsistent, since it in fact 
does buffering of character devices in some cases but does not in some 
others. In my example it reads 4096 bytes instead of requested 512 at 
each request, but when the program does fseek it rejects part of that 
buffer and does re-positioning and re-reading. Very confusing behaviour 
IMHO.

-Maxim

Dan Nelson wrote:
> In the last episode (Aug 03), Maxim Sobolev said:
> 
>>I have found the scenario in which our libc behaves utterly
>>suboptimally. Consider the following piece of code reads and
>>processes every other 512-bytes block in a file (error handling
>>intentionally omitted):
>>
>>What I have discovered in this case is that libc reads 4096 bytes
>>from the file for *each* fread(3) call, despite the fact that it can
>>only do one actual read(2) for every fourth fread(3) and satisfy the
>>rest from the internal buffer (4096 bytes). However, if I replace
>>fseek(3) with just another dummy fread(3) everything works as
>>expected - libc does only one read for every 8 fread(3) calls (4
>>dummy and 4 real).
>>
>>Is it something which should be fixed or are there some subtle
>>reasons for the current behaviour?
> 
> 
> I don't think stdio buffers character devices.  If you try it again,
> opening a regular file (I tried with /boot/kernel/kernel), you'll see
> much better behaviour.  There are still some unnecessary seeks though:
> 
> truss ./a.out
> 
> open("/boot/kernel/kernel",O_RDONLY,0666)        = 3 (0x3)
> fstat(3,{mode=-r-xr-xr-x ,inode=12295,size=4372853,blksize=8192}) = 0 (0x0)
> readlink("/etc/malloc.conf","AJ",63)             = 2 (0x2)
> issetugid()                                      = 0 (0x0)
> mmap(0x0,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 672555008 (0x28166000)
> break(0x804b000)                                 = 0 (0x0)
> break(0x804d000)                                 = 0 (0x0)
> read(3,"\^?ELF\^A\^A\^A\t\0\0\0\0\0\0\0\0\^B\0"...,8192) = 8192 (0x2000)
> read(3,"\0\0\0\0\0\0\0\0\M-u\^E\0\0\M-+\^V\0\0q"...,8192) = 8192 (0x2000)
> exit(0x0)
> 
> truss ./a.out 1
> 
> open("/boot/kernel/kernel",O_RDONLY,0666)        = 3 (0x3)
> fstat(3,{mode=-r-xr-xr-x ,inode=12295,size=4372853,blksize=8192}) = 0 (0x0)
> readlink("/etc/malloc.conf","AJ",63)             = 2 (0x2)
> issetugid()                                      = 0 (0x0)
> mmap(0x0,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 672555008 (0x28166000)
> break(0x804b000)                                 = 0 (0x0)
> break(0x804d000)                                 = 0 (0x0)
> read(3,"\^?ELF\^A\^A\^A\t\0\0\0\0\0\0\0\0\^B\0"...,8192) = 8192 (0x2000)
> lseek(3,0x0,SEEK_CUR)                            = 8192 (0x2000)
> lseek(3,0x2000,SEEK_SET)                         = 8192 (0x2000)
> read(3,"\0\0\0\0\0\0\0\0\M-u\^E\0\0\M-+\^V\0\0q"...,8192) = 8192 (0x2000)
> exit(0x0)
> 



More information about the freebsd-current mailing list