我正在尝试手动测试 SSD 在 NVMe 上的读写速度。我目前使用的方法是在 SSD 上安装一个文件系统,并以 4KB、32KB、128KB、215KB、1MB、64MB、256MB 和 1GB 的块大小读取/写入 20GB 的文件,同时记录读取/写入的开始时间和完成时间。此过程由 bash 脚本调用。bash 脚本将尝试通过调用以下函数 n 次来运行多个“应用程序”,每次都在后台运行该进程。
while [ $instCnt -le $appInstances ]
do
fsrw -w $blocksize /fsmnt/fs${instCnt}/usernumber1/j.j &
以下是 fsrw 可执行文件中的读取函数
bool perform_readop ()
{
// File descriptor.
int32_t fd = -1;
// Function status.
bool status = false;
//Zero read count
int zero_reads = 0;
// Open the file.
fd = open (fname.c_str (), O_RDONLY);
// Verify the file has been opened.
if (fd == -1)
{
cout << get_datetime_string() << "Read open of " << fname << " failed. Errno: "
<< errno << endl;
}
else
{
// Total bytes read.
uint64_t rd = 0;
// Elapsed time.
struct timeval tv = { 0 };
get_elapsed_time (&tv);
// Notify the user that the read test has started.
cout << get_datetime_string() << "Starting read" << endl;
while(rd < READ_LIMIT && zero_reads < 10) {
// Run until it is time for the test to stop.
ssize_t readsize = read (fd, &buf[0], blocksize);
if (readsize == -1)
{
cout << get_datetime_string << "Read failure. Errno: " << errno << endl;
zero_reads = 10;
}
else if (readsize == 0)
{
cout << get_datetime_string << "Reached EOF." << endl;
zero_reads++;
}
else
{
rd += readsize;
}
}
// Get the elapsed time.
get_elapsed_time (&tv);
// Report the number of bytes read.
cout << get_datetime_string() << "Read " << rd << " bytes in " << tv.tv_sec << "."
<< tv.tv_usec << " seconds, bytes per second " << bytes_per_second (&tv, rd) << endl;
// Close the file.
close (fd);
// Set the function return status when all read operations have
// been successful.
if (zero_reads < 10)
{
status = true;
}
}
return status;
}
我从其他人之前的工作中移植了这种方法,但我真的不确定这是否是验证 SSD 吞吐量的有效方法。测试结果,尤其是读取操作的结果,并不现实;它们比预期的要高得多。Fio 建议吞吐量应该在 500MB/s 左右,但这次测试记录的写入速度为 1GB+/s,读取速度接近 8GB/s
答案1
不清楚你的问题是什么 - 你似乎在问“为什么我的结果不切实际(为什么它们比 fio 的快?)”。你没有包括你的 fio 作业,所以不可能对此发表任何评论 :-( 我也不知道 fsrw 程序是做什么的。我会尝试看看剩下的内容:
假设我们只有您的程序和内核(这是一种简化)。您的程序发出写入,内核在将它们排队到内部缓冲区中时说“是的,我收到了”,从而允许您的程序继续运行。只有当内部内核缓冲区太满时,您的程序才会阻塞写入,直到有空间接受它。这意味着如果程序在安静的系统上写入“少量”数据,它永远不会等待磁盘为 I/O 提供服务 - 我们通过使用缓冲区将其与磁盘速度分离。显然,这种错觉只能持续一段时间,并且取决于缓冲区有多大、缓冲区有多满等等。
此外,如果有未使用的 RAM,则内核可以使用它来缓存部分磁盘。当我将数据写入磁盘时,如果有空间,我写入的数据不仅会被缓冲并在稍后刷新,而且可以在刷新完成后保留以备以后需要。您可以通过写入文件然后检查空闲空间来看到这种效果,通常您会看到 RAM 数量已经减少,因为该文件的部分内容被保存在缓存中。如果我最终从 Linux 的缓存中读取它,我实现的速度通常接近 RAM 的速度,并且磁盘不会受到影响(如果您知道如何使用 iostat,您会注意到当发生这种情况时它不会报告任何/太多的磁盘 I/O)。
所以:
- 正常写入 I/O 可以缓冲
- 正常 I/O 可以被缓存
- 读取缓存数据比读取未缓存数据快得多
- 你的读取程序容易受到上一点的影响
注意,这只是一种简化。我还没有介绍预读或文件系统交互等内容,为什么你fsync
这样做等等。
此外,内核向磁盘发送的块大小可能与程序提交的大小不同。您可能会向内核发送 16 x 4KB 连续写入,但内核可能会将它们合并在一起,并将单个 64KB 写入发送到磁盘。这在现实生活中通常是有益的,但在进行综合基准测试时您必须注意这一点。
总之,我猜你的结果是“不切实际的”,因为你从 Linux 的缓冲和缓存中受益匪浅。如果你的实际工作量确实是这样的,那么你的 SSD 速度就不是你的瓶颈,更快的磁盘对你没有多大帮助(所以“现实”是一个棘手的词)!通过确保你的数据集大小比系统中的总内存大小大很多倍(至少三倍),或者通过执行无法缓冲或缓存的 I/O,你可以获得更接近 SSD 本身的数字。我无法解释为什么你的速度比 fio 运行得慢,因为任何答案都是高度针对 fio 作业的,而且问题中没有包含任何作业。
答案2
打开 shell 提示符。
使用 dd 命令测量写入速度
dd if=/dev/zero of=/tmp/test1.img bs=1G count=1 oflag=dsync
使用 dd 命令测量延迟
dd if=/dev/zero of=/tmp/test2.img bs=512 count=1000 oflag=dsync
dd 命令对于找出简单的顺序 I/O 性能很有用。
使用 dd 命令测试读取速度
为了获得准确的读取测试数据,请首先通过运行以下命令在测试前丢弃缓存:
flush
echo 3 | sudo tee /proc/sys/vm/drop_caches
然后运行以下命令(创建 laptop.bin 之后):
dd if=/dev/zero of=/tmp/laptop.bin bs=1G count=1 oflag=direct