Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

speed comparison between fgetc/fputc and fread/fwrite in C

Tags:

performance

c

So(just for fun), i was just trying to write a C code to copy a file. I read around and it seems that all the functions to read from a stream call fgetc() (I hope this is this true?), so I used that function:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FILEr "img1.png"
#define FILEw "img2.png"
main()
{
    clock_t start,diff;
    int msec;
    FILE *fr,*fw;
    fr=fopen(FILEr,"r");
    fw=fopen(FILEw,"w");
    start=clock();
    while((!feof(fr)))
        fputc(fgetc(fr),fw);
    diff=clock()-start;
    msec=diff*1000/CLOCKS_PER_SEC;
    printf("Time taken %d seconds %d milliseconds\n", msec/1000, msec%1000);
    fclose(fr);
    fclose(fw);
}

This gave a run time of 140 ms for this file on a 2.10Ghz core2Duo T6500 Dell inspiron laptop. However, when I try using fread/fwrite, I get decreasing run time as I keep increasing the number of bytes(ie. variable st in the following code) transferred for each call until it peaks at around 10ms! Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FILEr "img1.png"
#define FILEw "img2.png"
main()
{
    clock_t start,diff;
    // number of bytes copied at each step
    size_t st=10000;
    int msec;
    FILE *fr,*fw;
    // placeholder for value that is read
    char *x;
    x=malloc(st);
    fr=fopen(FILEr,"r");
    fw=fopen(FILEw,"w");
    start=clock();
    while(!feof(fr))
     {
        fread(x,1,st,fr);
        fwrite(x,1,st,fw);
     }
    diff=clock()-start;
    msec=diff*1000/CLOCKS_PER_SEC;
    printf("Time taken %d seconds %d milliseconds\n", msec/1000, msec%1000);
    fclose(fr);
    fclose(fw);
    free(x);
}

Why this is happening? I.e if fread is actually multiple calls to fgetc then why the speed difference? EDIT: specified that "increasing number of bytes" refers to the variable st in the second code

like image 939
pratikm Avatar asked Nov 24 '11 00:11

pratikm


2 Answers

fread() is not calling fgetc() to read each byte.

It behaves as if calling fgetc() repeatedly, but it has direct access to the buffer that fgetc() reads from so it can directly copy a larger quantity of data.

like image 132
TJD Avatar answered Oct 06 '22 15:10

TJD


You are forgetting about file buffering (inode, dentry and page caches).

Clear them before you run:

echo 3 > /proc/sys/vm/drop_caches

Backgrounder:

Benchmarking is an art. Refer to bonnie++, iozone and phoronix for proper filesystem benchmarking. As a characteristic, bonnie++ won't allow a benchmark with a written volume of less than 2x the available system memory.

Why?

(answer: buffering effects!)

like image 38
sehe Avatar answered Oct 06 '22 15:10

sehe