C++ 中的 HDD 基准测试 - 测量的传输速度太快
Posted
技术标签:
【中文标题】C++ 中的 HDD 基准测试 - 测量的传输速度太快【英文标题】:HDD benchmark in C++ - measured transfer speed is too fast 【发布时间】:2015-04-04 13:17:41 【问题描述】:我正在尝试用 C++ 开发一个小型基准测试系统,但我无法测量 HDD 的读写速度。更准确地说,我测量的传输速度是巨大的:读取 400-600 MB/s,写入 1000 MB/s 以上。我有一个 5400 RPM 硬盘驱动器(不是 SSD),实际读/写速度(根据基准测试程序)大约是 60 MB/s。
//blockSize is 4096
//my data buffer
char* mydata = (char*)malloc(1*blockSize);
//initialized with random data
srand(time(NULL));
for(int i=0;i<blockSize;i++)
mydata[i] = rand()%256;
double startt, endt, difft;
int times = 10*25000;
int i=0,j=0;
DWORD written;
HANDLE f, g;
DWORD read;
f=CreateFileA(
"newfolder/myfile.txt",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(f==INVALID_HANDLE_VALUE)
std::cout<<"Error openning for write.";
return -1;
startt = clock();
for(i=0;i<times;i++)
WriteFile(
f,
mydata,
blockSize,
&written,
NULL
);
endt = clock();
difft = 1.0*(endt-startt)/(1.0*CLOCKS_PER_SEC);
std::cout<<"\nWrite time: "<<difft;
std::cout<<"\nWrite speed: "<<1.0*times*blockSize/difft/1024/1024<<" MB/s";
CloseHandle(f);
//------------------------------------------------------------------------------------------------
g=CreateFile("newfolder/myfile.txt",
GENERIC_READ,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(g==INVALID_HANDLE_VALUE)
std::cout<<"Error opening for read.";
return -1;
startt = clock();
for(i=0;i<times;i++)
ReadFile(
g,
mydata,
blockSize,
&read,
NULL
);
endt = clock();
difft = 1.0*(endt-startt)/(1.0*CLOCKS_PER_SEC);
std::cout<<"\nRead time:"<<difft;
std::cout<<"\nRead speed: "<<1.0*times*blockSize/difft/1024/1024<<" MB/s";
CloseHandle(g);
我也尝试过使用 fopen 和 fwrite 函数,得到了类似的结果。
我在另一台计算机上运行我的应用程序。写入速度差不多,读取速度还是很大的。
最有趣的是应用程序实际上在大约 2 秒内创建了一个 1GB 的文件,这对应于 500 MB/s 的写入速度。
有人知道我做错了什么吗?
【问题讨论】:
您的操作系统正在实现磁盘缓存; I/O 实际上并不是来自磁盘本身。 【参考方案1】:技术上,你没有做错任何事。问题是,每个操作系统都对所有 I/O 操作使用缓存。 HDD 本身也会缓存一些数据,因此它可以高效地执行它们。
这个问题是非常特定于平台的。您需要以某种方式欺骗缓存。
也许,你应该看看这个库:Bonnie++。您可能会发现它很有用。它是为 Unix 系统编写的,但源代码可以揭示一些有用的技术。
在 Windows 上,基于 this resource,传递给 CreateFile
函数的附加标志 FILE_FLAG_NO_BUFFERING
应该足以禁用此文件的缓冲。
引用:
在这些情况下,可以关闭缓存。这是在打开文件时通过将 FILE_FLAG_NO_BUFFERING 作为 CreateFile 的 dwFlagsAndAttributes 参数的值来完成的。禁用缓存时,所有读写操作都直接访问物理磁盘。但是,文件元数据可能仍会被缓存。要将元数据刷新到磁盘,请使用 FlushFileBuffers 函数。
【讨论】:
谢谢。我尝试了 FILE_FLAG_NO_BUFFERING 标志。现在我的写入速度大约是 3 MB/s。【参考方案2】:您正在测量缓存的性能。 尝试存储比这更多的数据,一旦缓存填满数据应该直接写入磁盘。
【讨论】:
【参考方案3】:我想我已经明白了。
无缓冲文件写入速度取决于WriteFile
函数正在写入的数据大小。我的实验表明,数据量越大,写入速度越高。对于大量数据(>1MB),它甚至优于缓冲写入,我可以通过写入大于 2GB 的数据来衡量。
总而言之,可以通过以下方式准确测量硬盘驱动器的写入速度:
使用CreateFile
打开文件并设置FILE_FLAG_NO_BUFFERING
标志。
一次写入大量数据,使用WriteFile
。
【讨论】:
以上是关于C++ 中的 HDD 基准测试 - 测量的传输速度太快的主要内容,如果未能解决你的问题,请参考以下文章
SSD上的NLog FileTarget在基准测试中比HDD慢?