tags:

views:

829

answers:

3

Okay, this is for a homework; although I'm not requesting any help on the programming side. It's already done :)

After providing the same program which reads a random generated input file and echoes the same string it readed to an output. The only difference is that on one side I'm providing the read and write methods from linux syscals, and on the other side I'm using fread/fwrite.

Timing my application with an input of 10Mb in size and echoing it to /dev/null, and making sure the file in not cached, I've found that libc's frwite is faster by a LARGE scale when using very small buffers (1 byte in case).

Here is my output from time, using fwrite:

real    0m0.948s
user    0m0.780s
sys     0m0.012s

And with write syscall:

real    0m8.607s
user    0m0.972s
sys     0m7.624s

The only possibility that I've thought is that internally libc is already buffering my input... Unfortunately I couldn't find that much information around the web, so maybe the gurus here could help me out...

Thanks

+8  A: 

Timing my application with an input of 10Mb in size and echoing it to /dev/null, and making sure the file in not cached, I've found that libc's frwite is faster by a LARGE scale when using very small buffers (1 byte in case).

fwrite works on streams, which are buffered. Therefore many small buffers will be faster because it won't run a costly system call until the buffer fills up (or you flush it or close the stream). On the other hand, small buffers being sent to write will run a costly system call for each buffer - that's where you're losing the speed. With a 1024 byte stream buffer, and writing 1 byte buffers, you're looking at 1024 write calls for each kilobyte, rather than 1024 fwrite calls turning into one write - see the difference?

For big buffers the difference will be small, because there will be less buffering, and therefore a more consistent number of system calls between fwrite and write.

If you want to read more about it, you can have a look at this document, which explains standard I/O streams.

Matthew Iselin
+2  A: 

You can also disable buffering with setbuf() function. When the buffering is disabled, fwrite() will be as slow as write() if not slower.

More information on this subject can be found there: http://www.gnu.org/s/libc/manual/html_node/Controlling-Buffering.html

dmityugov
+1  A: 

write(2) is the fundamental kernel operation.

fwrite(3) is a library function that adds buffering on top of write(2).

For small byte counts, fwrite(3) is faster, because of the overhead for just doing a kernel call.

For large byte counts, write(2) is faster, because it doesn't bother with buffering and you have to call the kernel in both cases.

If you look at the source to cp(1), you probably won't see any buffering.

DigitalRoss