【问题标题】:How to correctly time speed of writing to a disk (i.e. file) in C如何在 C 中正确计时写入磁盘(即文件)的速度
【发布时间】:2022-02-08 17:43:15
【问题描述】:

我有一个运行 Linux 系统的 Zynq SoC,我想计算我可以用 C 语言写入其 SD 卡的速度。

我已经尝试过clock()clock_gettime(),对于后者,我做了以下操作:

#define BILLION 1000000000.0
#define BUFFER_SIZE 2097152
...

for (int i=0; i<100; i++) {
    memcpy(buf, channel->dma + offset, BUFFER_SIZE);
    
    /* Open file for output */
    FILE *f = fopen(path, "w");

    /* Start timer */
    clock_gettime(CLOCK_MONOTONIC, &start);

    /* Write data from cpu ram to sd card*/
    fwrite(buf, 1, BUFFER_SIZE, f);
    fclose(f);

    /* Stop timer and report result */
    clock_gettime(CLOCK_MONOTONIC, &end);
    elapsed_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / BILLION;
    printf("%lf seconds\n", elapsed_time);
}

对于 2097152 字节,我得到的时间约为 0.019 秒,我认为这是错误的,因为写入 SD 卡的速度被引用为 10 MB/s,不可能是 110 MB/s我似乎得到了。当我改为将计时代码放在循环之外,并且基本上计算写入整个 100*BUFFER_SIZE 所需的时间时,我得到了更合理的 18 MB/s。

我的问题是,尝试为单个 fwrite 操作计时是否不正确? clock_gettime() 没有给我足够的准确度/精度吗?我希望获得尽可能快的写入磁盘速度的最准确值,因为它是系统设计中的一个非常重要的参数,因此我得到的这种差异相当令人不安。

【问题讨论】:

  • clock() 在某些系统上可能具有相当粗略的粒度,使其仅适用于需要几秒钟的定时操作。您还必须关闭磁盘缓冲,或者写入如此大的数量,以致其中大部分内容仍无法在缓存中。
  • 有很多“级别”可以发生缓冲:硬件级别、设备驱动程序级别、操作系统级别、C 库级别(您可以使用fclose())、应用程序级别(您可以这覆盖了fwrite())...
  • 对单个fwrite 操作计时是否不正确?对于一个字节,是的。对于SIZE_MAX 字节,没有。
  • 顺便说一句,请记住,您正在编写一个程序来计算延迟,而不是吞吐量。从延迟计算吞吐量并非易事:您似乎假设latency = size_of_write / write_speed,由于页面缓存(Linux),fclose(Linux 运行,磁盘可能空闲)等原因通常是错误的。一个更好的选项可能是对页面缓存中的页面进行大量更改,然后为 fsync 操作计时。
  • 谢谢大家。感谢@TSG 了解天真的延迟公式。会在我的报告中出现令人尴尬的部分。

标签: c linux time


【解决方案1】:

Linux 内核经常缓存对磁盘存储的读写访问。也就是说,它从 write 调用返回并在后台进行实际写入。它透明地执行此操作,因此如果您在写入后读取同一个文件,您将获得您写入的结果,即使它们尚未传输并完全写入磁盘。

要强制完成写入,您可以调用fsync 函数。它会阻塞,直到特定文件的所有文件 IO 完成。在你的情况下,打电话给

#include <unistd.h>

...
fwrite(...);
fsync(fileno(f));

应该够了。

编辑
正如 cmets 中提到的@pmg,还有流级别的缓冲。虽然它可能不是那么大的缓冲区,但您可以通过在 fsync 之前调用 fflush() 来强制写入流缓冲区。

【讨论】:

  • 谢谢! fsync 像魔术一样工作。为了安全起见,我也会将fflush 移到文件中并将fclose() 移出时间。
  • 您可能还想尝试openO_SYNC,但这应该不会与在写入后使用fsync 有太大差异。
猜你喜欢
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-27
  • 2015-11-23
  • 2012-07-19
  • 1970-01-01
  • 2012-06-27
相关资源
最近更新 更多