【问题标题】:SSD read performanceSSD 读取性能
【发布时间】:2021-03-28 05:43:50
【问题描述】:

在我的应用程序中,它将一个大文件 (650GB) 写入 SSD。其中包含大量约 1k 条消息。消息不是固定长度的。因此,我根据几个消息过滤条件的需要维护一个内存索引。索引包含文件的位置。

在一种情况下,一个索引中几乎所有对应的消息都以大约 63,000 字节的距离写入磁盘。这意味着当读取一条消息 (~1k) 时,应用程序必须在文件中寻找另一个 ~63,000 条消息以读取下一条消息。当 OS 磁盘缓存被删除时(sync; echo 1 > /proc/sys/vm/drop_caches;),应用程序每秒只能读取大约 12,000 条消息。那是 12MB/秒。那是实际行为吗?请指教。 我准备了一个小应用程序来模拟。

#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <iostream>
#include <unistd.h>

using namespace std;

uint64_t gethrtime_us()
{
        timeval tv;
        gettimeofday(&tv, NULL);
        uint64_t t = tv.tv_sec;
        t = t * 1000 * 1000 + tv.tv_usec;
        return t;
}

int main(int argc, const char** argv)
{
    uint64_t gap = atol(argv[1]);
    uint64_t messages = atol(argv[2]);

    int32_t fd = open("/mnt/OC/data", O_RDONLY);// data.txt is 650GB binary data
    if (fd < 0)
    {
        cout << "Open Error" << endl;
        return 1;
    }

    uint64_t startTime = gethrtime_us();
    uint64_t totalReadSize = 0;
    for (uint64_t i = 0 ; i < messages ; i++)
    {
        char message[1024];
        if (read(fd, message, 1024) != 1024)
        {
            cout << "Read Error @" << i << endl;
            break;
        }
        if (lseek(fd, gap, SEEK_CUR) == -1)
        {
            cout << "Seek Error @" << i << endl;
            break;
        }
    }
    uint64_t endTime = gethrtime_us();
    cout << "Time taken " << (endTime - startTime) << " micro seconds" << endl;

    return 0;
}

测试结果如下。

root@comp|centos7|3.10.0-957.5.1.el7:0:bin # g++ -std=c++11 -O3 Main.cpp;
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 0 100000
Time taken 172105 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 1000 100000
Time taken 318472 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 2000 100000
Time taken 446191 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 3000 100000
Time taken 561590 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 4000 100000
Time taken 702702 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 5000 100000
Time taken 874044 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 6000 100000
Time taken 1105384 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 7000 100000
Time taken 1698921 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 8000 100000
Time taken 1165863 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 9000 100000
Time taken 7445158 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 10000 100000
Time taken 8033516 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 15000 100000
Time taken 8950091 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 20000 100000
Time taken 9135020 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 30000 100000
Time taken 9180888 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 40000 100000
Time taken 9123635 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 50000 100000
Time taken 9181108 micro seconds
root@comp|centos7|3.10.0-957.5.1.el7:0:bin # sync; echo 1 > /proc/sys/vm/drop_caches; ./a.out 60000 100000
Time taken 9141465 micro seconds

在最后一种情况下,每 9 秒有 100000 条消息。 (100000 * 1k) / 9 = 11111kb/s

我很担心为什么 SDD 制造商声称 ~2.3 GB/s 的顺序读取速率获得了 OC 磁盘缓存的好处,而在这种情况下他们只能做到 12MB/s。 请指教。

【问题讨论】:

  • 小型随机写入的典型写入速度低于 200 MB/s。以下是一些信息:https://www.thessdreview.com/ssd-guides/beginners-guide/the-ssd-manufacturers-bluff/2/ 查看前 4K 数字,而不是 QD32 或线程 4K。
  • 对于小的随机 I/O,MBPS 没有意义。测量 IOPS。由于您正在通过文件系统,因此 I/O 比程序中明确的 I/O 多。使用 iostat 之类的工具进行测量。
  • 这些是“内存索引”字节偏移还是消息索引偏移?
  • 我认为制造商声称 ~2.3 GB/s 顺序读取速率,然后在“随机且非常非顺序读取”中没有提供 ~2,3 GB/s 没有任何问题” 情况。
  • 如果可以的话,我还建议尝试异步 IO。使用阻塞 IO(例如read()),SSD 可能将一半的时间用于等待下一个读取请求,而 CPU 将另一半时间用于等待前一个读取完成。对于顺序读取,这可以通过在请求数据之前检测模式和预取数据来“隐藏”(在操作系统和 SSD 中)。

标签: c++ c performance file-read solid-state-drive


【解决方案1】:

我认为您应该使用磁盘基准测试应用程序来测试您的 SSD 性能。看 https://www.raymond.cc/blog/measure-actual-hard-disk-perfomance-under-windows/

也就是说,读取相对较小的数据块涉及系统调用和所有相关的操作系统开销。您最好绕过文件系统并从原始设备读取。在 Linux 上,具有 root 访问权限,您只需从 /dev/sda 或 sdb (代表整个磁盘)读取。有了必要的权限,您也可以在 Windows 上执行此操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2023-03-27
    • 1970-01-01
    • 2018-09-20
    相关资源
    最近更新 更多