Performance issues with glibc stdio and multithreading on SMP machines

Eric Dumazet dada1@cosmosbay.com
Tue Apr 25 12:16:00 GMT 2006


glibc stdio default buffer allocation uses ALLOC_BUF() macro defined in 
libio/libioP.h, with a size of 4096 bytes (on linux at least).

This macro uses a mmap() call :  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)

At fclose() time, the allocated buffer is then freed with munmap() call.

typicall strace call for { fopen(); fread(...);fclose(..);} is

  open("/path_to_file", O_RDONLY) = 3
  fstat64(3, {st_mode=S_IFREG|0644, st_size=70001, ...}) = 0
  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 
0) = 0xb7d46000
  read(3, 0xb7d46000, 4096) = 4096
...
  close(3)                          = 0
  munmap(0xb7d46000, 4096)          = 0


It is a *big* performance problem for multithreaded apps because 
mmap()/munmap() calls have scalability issues.
These calls must lock the list of vmas of the process, and invalidate 
TLB (using expensive inter processor messages in SMP machines). Also, 
the first access to the newly mmaped() buffer done at read() time 
triggers a page fault, that might take a spinlock or rwlock in kernel to 
resolve the fault.

User apps can solve this by using setvbuf() call after fopen(), giving a 
buffer that is allocated by a normal malloc() call. But the buffer must 
be freed at fclose() time too.

Could glibc use :

- ordinary malloced buffers
- or a (small) cache of buffers (to avoid munmap() and then a further 
mmap())

Thank you
Eric Dumazet




More information about the Libc-alpha mailing list