fopen、fclose的效率
如果在嵌套的for循环中迭代写入文件,那么在循环之前打开文件,在循环之后关闭文件,而不是在循环中打开和关闭文件,在效率上是否有任何区别?见下文:fopen、fclose的效率,c,performance,for-loop,io,fopen,C,Performance,For Loop,Io,Fopen,如果在嵌套的for循环中迭代写入文件,那么在循环之前打开文件,在循环之后关闭文件,而不是在循环中打开和关闭文件,在效率上是否有任何区别?见下文: 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++){ fp
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;
}
intmain(){
文件*file1;
字符文件名;
int i,j,N,M;
对于(i=0;iYes),存在差异。fopen()和fclose()映射到open()和close()上系统调用,它需要一个中断来触发一个上下文切换来运行内核代码。我做了一个快速的基准测试,看看是否有显著的差异。代码与您的代码略有不同,但它仍然显示出效率上的差异。另外,我没有考虑缓存等
你可以自己看看这是否重要
测试程序:
#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;
}
这台机器是2.2GHz核心i7,8GB内存,运行OS X
结果是:
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次迭代之前,用户不太可能注意到这种差异。任何更高的东西,你都会开始看到两种不同实现在运行时间上的一些显著差异
归根结底,如果您可以不费吹灰之力地高效编码,为什么还要故意使用效率较低的算法呢?如果您关心性能,您可能不想执行额外的打开和关闭操作。但是如果您非常关心避免数据丢失,那么您可能希望打开以进行追加、写入和关闭例如,如果您要添加一个调试打印模块,您可能不太关心性能,而只关心保持每一位输出
例如:
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);
}
为什么不对它进行基准测试并自己找出答案?为什么有人会使用第一个代码段?好吧,在第一种情况下,您要做更多的工作,所以需要更长的时间。无论它是否对实时性产生影响,您只能使用基准测试来找出答案。保持文件打开通常更有效,因为缓冲区和缓存可以刷新当你关闭文件时,它会自动关闭。但是,如果你担心在崩溃或电源故障的情况下丢失数据,那么你可能需要采取更具防御性的方法,反复打开和关闭文件。@PaulR你不想让文件系统或操作系统更好地处理电源故障吗?我也考虑过这一点,但在发生故障的情况下fprintf
,文件仍然以任何方式打开。使用缓存和all,即使文件已关闭,也可能不会向磁盘写入任何内容。-1.系统调用的触发方式完全取决于体系结构。使用中断是启动系统调用的多种方法之一。True。我暗指的是Linux x86。我的错。在操作系统设计术语中,任何这样的内核条目都被称为“中断”,而不仅仅是使用相同机制的硬件中断和软件中断。“中断”过载过多,IMHO.Java等又增加了一个过载,这个术语现在产生了很多混乱;(我所说的中断是指x86上触发同步中断的int汇编指令。
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
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);
}