【问题标题】:fopen takes more time with "w" than "a" modefopen 在 "w" 模式下比 "a" 模式花费更多时间
【发布时间】:2015-01-14 20:13:46
【问题描述】:

fopen 和 fclose 在 "w" 模式下打开时是否比 "a" 模式下在以下情况下花费更多时间 1.文件已经存在 2. 没有文件存在 以下内容 日志文件 = fopen(log,"a"); 和 logFile = fopen(log,"w");

我有以下代码,我对它进行了快速 strace 分析,以获取每个系统调用的时钟周期,而在测试开始时没有文件存在。

代码

int main(int argc, char **argv)
{
    const char* log = "log.txt";
    FILE* logFile = NULL;
    char timeBuf[100];
    time_t now;
    struct tm *logtime1;

    time(&now);
    logtime1 = localtime(&now);
    strftime(timeBuf,sizeof(timeBuf),"[%Y-%m-%d %H:%M:%S]",logtime1);
    int i;
    char *inMessage = "The Quick Brown Fox Jumps Over The Lazy Dog";
    for(i=0;i<50000;i++)
    {
        logFile = fopen(log,"a"); //or **logFile = fopen(log,"w");**
        if(logFile != NULL)
        {
           fflush( 0 );
           int error = 0;

           fprintf(logFile, "%s\t%s %d at (%s:%d)\n",timeBuf,
           inMessage, error,__FILE__, __LINE__);
           fclose(logFile);
        }
   }
   return 0;

}


当我以“w”模式打开文件时,strace 分析显示在打开系统调用中需要更多时间。这背后有什么原因吗?

以下是两个配置文件

  1. --------- 使用“w”模式跟踪代码

    strace -c ./test.out -o 报告

    % time seconds usecs/call calls errors syscal


    76.17 0.522555 10 50006 打开

    12.13 0.083197 2 50006 关闭

    4.61 0.031626 1 50000 写入

    3.96 0.027151 1 50002 munmap

    1.57 0.010737 0 50017 映射

    1.55 0.010663 0 50007 fstat


    100.00 0.686068 300060 共 1 个

    1. 使用“a”模式跟踪代码

    --------- strace -c ./test.out -o 报告

    % time seconds usecs/call 调用错误 syscall


    22.08 0.020467 0 50002 munmap

    20.24 0.018763 0 50000 写入

    16.76 0.015542 0 100007 fstat

    13.43 0.012450 0 50006 打开

    9.90 0.009177 0 50006 关闭

    9.44 0.008756 0 50017 映射

    8.15 0.007558 0 50001 lseek


    100.00 0.092713 400060 共 1 个

【问题讨论】:

  • w 将截断您正在打开的文件。如果它是一个“大”文件,操作系统需要一段时间才能清理干净。
  • 我认为打开文件的性能更多地取决于操作系统的实现,因为它是一个系统调用。
  • 有意义的是,在“w”模式下截断文件将占用操作系统一些周期(取决于实现)。谢谢
  • 您要测量的内容很大程度上取决于实施; “a”和“w”做不同的事情不一定可比。并考虑在对程序进行计时时,应在不同条件下重复多次测量:考虑操作系统需要时间在磁盘中查找文件,但后续访问会更快,因为缓存信息甚至磁盘磁头更接近文件内容。也就是说,从冷启动运行的第一个程序最终会支付 I/O 开销,并且比第二个程序花费更长的时间。
  • 我同意你的看法,但只是为了让你知道我对这两种实现进行了多次分析,结果相似。此外,我认为代码运行了 50000 次迭代,我可以忽略两种实现的初始 I/O 开销。我不能吗?

标签: c++ c


【解决方案1】:

使用mode="w",文件在写入之前被清空,所以系统必须:

  1. 将文件大小重置为零(打开)
  2. 将磁盘上使用的块标记为未使用(打开)
  3. 分配新块(写入)
  4. 更新文件大小(写入)

mode="a",系统只有:

  1. 分配一个新块(有时,并非总是,如果您写入的内容进入一个新块)
  2. 更新文件大小(写入)

显然,mode="w" 做更多的工作需要更多的时间......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2022-09-30
    • 2017-12-29
    • 2021-11-12
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多