c - 写入大文件时带宽读数增加

标签 c fwrite gettimeofday

我们在类里面使用 gettimeofday 测量了两个外部 HDD 的带宽。

令人惊讶的是,经过多次重复(每次执行三次测量,执行三次),我们发现在两个 HDD 上写入 2500MB 文件比写入较小的文件更快。

Bandwidth chart

这是我们的 C 代码。从 python 脚本调用它来生成一些图表。

//argv[1] = path, argv[2] = size in MB (2500 in this case)

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


struct timeval tv0;
struct timeval tv1;

int main(int argc, char *argv[]){
    unsigned long size=atoi(argv[2])*1000L*1000L;
    int f = open(argv[1], O_CREAT|O_WRONLY|O_TRUNC, 0777);
    char * array = malloc(size);
    gettimeofday(&tv0, 0); //START TIME
    write(f, array, size);
    fdatasync(f);
    close(f);
    gettimeofday(&tv1, 0); // END TIME 
    double seconds = (((double)tv1.tv_sec*1000000.0 + (double)tv1.tv_usec) - ((double)tv0.tv_sec*1000000.0 + (double)tv0.tv_usec))/1000000.0;
    printf("%f",seconds);
}

老师不知道,所以我在这里问:是否有原因会发生这种情况?

最佳答案

您的基准测试存在严重缺陷:

  • 它在不检查的情况下假设所有函数调用都成功且没有错误。
  • 它假设成功后,write() 将写入指定给它的全部字节数,但我们不能保证一定会这样做。

如果您的假设结果不满足,其中任何一个都可能很容易使您的基准测试结果无效,并且至少第二个很可能会出现这种情况。

请特别注意,write()ssize_t 形式返回写入的字节数。 ssize_t 是有符号整数类型,其具体宽度取决于系统。如果您的大小是 32 位,则 write() 无法在一次调用中写入所有 2500MB 缓冲区,因为这比带符号的 32 位整数要多代表(限制略高于 2100 MB)。

此外,您的程序假设它可以成功分配非常大的内存块,但事实很可能并非如此。但是,如果这个假设失败,您可能会遭遇崩溃。

关于c - 写入大文件时带宽读数增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36410760/

相关文章:

c - 检测到堆损坏 : after Normal block

atomic - 内存映射文件和单个 block 的原子写入

c - 在 C 中使用 fread() 从二进制文件读取时出现奇怪的值

c - C程序中的 undefined reference 错误

c - 减去指针后的输出

c - 在c中将ByteArray写入文件

c - 如何使用 gettimeofday() 或与 Visual Studio C++ 2008 等效的东西?

c - C 中的 -mno-sse 标志和 gettimeofday() 出错

c - 为什么 gettimeofday 返回奇怪的 tv_sec?

c - 无论 fork() 多少次,父进程仅从其子进程接收到 SIGCHLD 一两次