【发布时间】: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 了解天真的延迟公式。会在我的报告中出现令人尴尬的部分。