File descriptor vs standard I/O

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.