Here's another example that compares access using file descriptors and standard I/O on an x86 PIII-725 machine with a UDMA-4 EIDE disk, using the QNX 4 filesystem.
The table lists the rates, in megabytes per seconds, for writing and reading a 256 MB file, using file descriptors and standard I/O:
Record size | FD write | FD read | Stdio write | Stdio read |
---|---|---|---|---|
32 | 1.5 | 1.7 | 10.9 | 12.7 |
64 | 2.8 | 3.1 | 11.7 | 14.3 |
128 | 5.0 | 5.6 | 12.0 | 15.1 |
256 | 8.0 | 9.0 | 12.4 | 15.2 |
512 | 10.8 | 12.9 | 13.2 | 16.0 |
1024 | 14.1 | 16.9 | 13.1 | 16.3 |
2048 | 16.1 | 20.6 | 13.2 | 16.5 |
4096 | 17.1 | 24.0 | 13.9 | 16.5 |
8192 | 18.3 | 31.4 | 14.0 | 16.4 |
16384 | 18.1 | 37.3 | 14.3 | 16.4 |
Notice how the read() access is very sensitive to the record size; this is because each read() maps to an _IO_READ message and is basically a context-switch and message-pass to the filesystem; when only small amounts of data are transferred each time, the OS overhead becomes significant.
Since standard I/O access using fread() uses a 1 KB internal buffer, the number of _IO_READ messages remains constant, regardless of the user record size, and the throughput resembles that of the file-descriptor 1 KB access in all cases (with slight degradation at smaller record sizes due to the increased number of libc calls made). Thus, you should consider the anticipated file-access patterns when you choose from these I/O paradigms.