为什么使用fsync()刷新写入磁盘会加快访问速度?

时间:2012-11-12 01:09:41

标签: c performance fsync

我们需要尽可能多的应用程序,保证在报告记录持续存在时,确实如此。我知道要执行此操作,请使用fsync(fd)。但是,由于某些奇怪的原因,使用fsync()会加速写入磁盘的代码,而不是像预期的那样减慢速度。

一些示例测试代码返回以下结果:

no sync() seconds:0.013388   writes per second:0.000001 
   sync() seconds:0.006268   writes per second:0.000002

以下是产生这些结果的代码:

#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>

void withSync() {
    int f = open( "/tmp/t8" , O_RDWR | O_CREAT );
    lseek (f, 0, SEEK_SET );
    int records = 10*1000;
    clock_t ustart = clock();
    for(int i = 0; i < records; i++) {
        write(f, "012345678901234567890123456789" , 30);
        fsync(f);
    }
    clock_t uend = clock();
    close (f);
    printf("   sync() seconds:%lf   writes per second:%lf\n", ((double)(uend-ustart))/(CLOCKS_PER_SEC), ((double)records)/((double)(uend-ustart))/(CLOCKS_PER_SEC));
}

void withoutSync() {
    int f = open( "/tmp/t10" , O_RDWR | O_CREAT );
    lseek (f, 0, SEEK_SET );
    int records = 10*1000;
    clock_t ustart = clock();
    for(int i = 0; i < records; i++) {
        write(f, "012345678901234567890123456789" , 30 );
    }
    clock_t uend = clock();
    close (f);
    printf("no sync() seconds:%lf   writes per second:%lf \n", ((double)(uend-ustart))/(CLOCKS_PER_SEC), ((double)records)/((double)(uend-ustart))/(CLOCKS_PER_SEC));
}

int main(int argc, const char * argv[])
{
    withoutSync();
    withSync();
    return 0;
}

2 个答案:

答案 0 :(得分:9)

问题在于您尝试计时I / O写入的方式。您在语义上想要测量I / O记录写入之间的挂钟时间,但您使用的是C库函数clock,它测量CPU执行时间而不是总时间。使用clock_gettime时钟选择CLOCK_MONOTONIC或理想情况下CLOCK_MONOTONIC_RAW(后者是Linux扩展名)。

您没有收集调用clock之间经过的总时间:您正在收集进程旋转CPU周期的时间估计值。您的磁盘I / O(特别是对writefsync的调用)都是阻塞的,这意味着每个系统调用都由内核代表您处理,并且不会占用您的CPU过程背景。因此,您需要测量挂钟时间中的实际差异,这听起来是现实世界中经过的总时间,超出了测试程序流程的范围。实际上,fsync根本不关心CPU时间。大多数I / O操作的执行时间不会由内核甚至CPU处​​理;它将归功于磁盘控制器。

此外,小记录大小可以作为基准。它是同步I / O的常见用例(例如,为事务日志写入元数据)。为了获得更大记录大小的时序稳定性,只需在每个定时器间隔和平均/摊销中显着增加循环迭代次数。这将准确地模拟正在写入和同步刷新的小阻塞记录的成本。

请考虑fdatasync以提高效果。

答案 1 :(得分:0)

非常感谢您的评论,谢谢!表明将测试增加到大量交易的评论是正确的。使用大量交易fsync()时似乎确实有所作为。至少在OS / X 10.8上:

  1. 当写入不增加文件大小时,fsync()会使完成写入所需的时间加倍。
  2. 当写入确实增加文件大小时,fsync()明显变慢。