The effectiveness of fopen, fclose

If iteratively writing to a file in a nested loop, is there a difference in performance to open the file before the loop and close it after, rather than open and close inside? See the following:

int main(){
    FILE *file1;
    char filename;
    int i, j, N, M;

    for(i=0; i<N; i++){
        file1=fopen(filename, "a");
        for(j=0; j<M; j++){
            fprintf(file1,"%d %d\n", i, j);
        }
        fclose(file1);
    }
return 1;
}

or

int main(){
    FILE *file1;
    char filename;
    int i, j, N, M;

    file1=fopen(filename, "a");
    for(i=0; i<N; i++){
        for(j=0; j<M; j++){
            fprintf(file1, "%d %d\n", i, j);
        }
    }
    fclose(file1);
    return 1;
}
+2
source share
3 answers

I did a quick test to see if there is a significant difference. The code is slightly different from yours, but it still shows a difference in performance. In addition, I did not bother to take into account caching, etc.

You can see for yourself if this is significant.

Testing program:

#include <stdio.h>
#include <stdlib.h>


#ifdef TEST1
void test(char *filename, int n) {
    int i;
    FILE *fp;

    for (i=0; i<n; i++) {
        fp = fopen(filename, "a");
        if (fp) {
            fprintf(fp, "%d\n", i);
            fclose(fp);
        }
    }
}
#else
void test(char *filename, int n) {
    int i;
    FILE *fp;

    fp = fopen(filename, "a");
    if (!fp)
        return;

    for (i=0; i<n; i++) {
        fprintf(fp, "%d\n", i);
    }

    fclose(fp);
}
#endif

int main(int argc, char *argv[]) {
    char *filename;
    int n;

    if (argc < 3)
        return -1;

    filename = argv[1];
    n = atoi(argv[2]);

    test(filename, n);

    return 0;
}

Compilation and labeling commands:

gcc -DTEST1 -Wall -O3 -o test1 test.c
gcc -DTEST2 -Wall -O3 -o test2 test.c

time ./test1 test.bin n; rm test.bin # where n is the number of runs
time ./test2 test.bin n; rm test.bin # where n is the number of runs

The machine has a 2.6 GHz Core i7, 8 GB of RAM, running under OS X.

Results:

   n   |  test1  |  test2
-------+---------+---------
10     | 0.009s  | 0.006s
100    | 0.036s  | 0.006s
1000   | 0.340s  | 0.007s
10000  | 2.535s  | 0.011s
100000 | 24.509s | 0.041s

, , ? .

? , () .

? . ? 1000 . - , .

, , ?

+10

, , , . , , , . , , , , , .

:

void debug_print(char *debug_string)
{
  struct timespec *now;
  int success = clock_gettime(CLOCK_REALTIME, &now);
  /* We ignore errors in the file I/O, because if we can't write to the debug file we have no place to report the problem. */
  FILE *f = fopen("debug.text", "a");
  if (success) {
    fwrite(f, "time %d.%9d: %s\n", now.tv_sec, now.tv_nsec, debug_string);
  } else {
    fwrite(f, "time errno=%d: %s\n", errno, debug_string);
  }
  fclose(f);
}
+3

Yes, there is a difference. fopen () and fclose () to open () and closed () system calls that require an interrupt to trigger a context switch to run kernel code.

+1
source

Source: https://habr.com/ru/post/1653354/


All Articles