C 文件I/O性能太好以至于不可能是真的?

C 文件I/O性能太好以至于不可能是真的?,c,performance,file,io,C,Performance,File,Io,我运行了一个简单的文件I/O性能测试。我将1GB的数据写入一个文件,并测量经过的时间。结果表明,写入时间仅需约0.45秒,性能超过17Gbps。我知道这是不可能的,但我在测试代码中找不到任何错误。下面是我的测试程序。我可以在d:\a.bin中看到正确的文件 #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { char *ioBuf; int i, io_b

我运行了一个简单的文件I/O性能测试。我将1GB的数据写入一个文件,并测量经过的时间。结果表明,写入时间仅需约0.45秒,性能超过17Gbps。我知道这是不可能的,但我在测试代码中找不到任何错误。下面是我的测试程序。我可以在d:\a.bin中看到正确的文件

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

int main()
{
    char *ioBuf;
    int i, io_buf_size = 1024 * 1024;
    unsigned int io_amt = 0;
    FILE *fp;
    clock_t start, end;
    double elapsed;

    ioBuf = (char *)malloc(1024 * 1024 * sizeof(char));

    for (i = 0; i < io_buf_size; i++) {
        ioBuf[i] = i % 255;
    }

    if ((fp = fopen("d:\\a.bin", "wb")) == NULL) {
        printf("open file fail, err  \n");
        return 1;
    }

    start = clock();
    for (i = 0; i < 1024; i++) {
        io_amt += fwrite(ioBuf, sizeof(char), io_buf_size, fp);
        if (fflush(fp) != 0) printf("flushing buffer failed!\n");
    }
    end = clock();
    elapsed = (double)(end - start) / CLOCKS_PER_SEC;
    printf("fwrtie %dGB takes : %f sec\n", io_amt / (1024 * 1024 * 1024), elapsed);

    fclose(fp);
    free(ioBuf);
    return 0;
}
#包括
#包括
#包括
int main()
{
char*ioBuf;
int i,io_buf_size=1024*1024;
无符号国际货币单位金额=0;
文件*fp;
时钟开始、结束;
双倍过去;
ioBuf=(char*)malloc(1024*1024*sizeof(char));
对于(i=0;i
操作系统通常在RAM中缓存写操作,并仅在通常以秒为单位的一段时间后(取决于具体的操作系统配置)才将它们写出来。除此之外,您的磁盘驱动器也可能有RAM缓存1

如果您写入了足够的数据(例如,超过您拥有的RAM数量),您将在某个时候看到急剧减速,因为操作系统现在必须同步写入文件数据,以便为您的新写入腾出空间

请注意,此操作系统级缓存与执行
fwrite
时标准库可能执行的缓存不同-您正在写入1 MB块,因此可能看不到标准库缓存,并且在任何情况下,当您
fclose()
文件时,这些缓冲区将被刷新

要测量真实速度,您有多种选择。假设您在像Linux这样的POSIX系统上,您可以在可以从中获得的整数文件描述符上使用。这将刷新操作系统缓冲区,并指示磁盘写出任何非持久性磁盘缓冲区。或者完全放弃C库
f*
函数,使用操作系统级例程打开文件
O_DIRECT

最后,如注释中所述,文件的内容是一个简单的重复模式(周期为255字节)。使用压缩或重复数据消除的文件系统可能很容易将此文件存储在其标称大小的一小部分中,即使正确使用
fsync
,也会导致明显的“超乎寻常”写入速度。为避免这种可能性,请写入随机数据



1旋转磁盘上的缓存通常为10 MB,但在SSD上不太常见。

如果文件位于RAM中,操作系统会自动缓存文件系统,以防止无用的物理访问并加快写入速度。此例程每写入1MB,就会调用fflush()。它不是强制将数据写入物理介质吗?
fflush()
仅将数据从流发送到文件缓冲区,操作系统仍然可以执行优化,除非您禁用它们。查看此答案了解更多信息:驱动器也将自己进行缓存。如果是有日志记录的fs,“编写文件”将在稍后的某个时间跟进,并将日志刷新到fs。一切都很复杂!是的,但至少驱动器缓存通常被限制在几十MB,而且
fsync
应该会在操作系统和驱动器级别引起刷新。通过本机压缩,写入文件系统也可能获得“难以置信的”性能。写一些像全零这样的东西,你可以得到一些疯狂的“原始”IO号,即使数据一直安全地同步到磁盘上。甚至这个问题的数据模式都是高度可压缩的,任何半途而废的压缩算法只需增加一个计数器即可。@AndrewHenle-好的,我更新了这个问题以反映这一点以及bazza关于磁盘缓冲区的评论。你们都很棒!谢谢。