rust 从文件的许多随机点快速阅读

polhcujo  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(113)

我正在Rust中开发一个性能关键型网络服务。对我的服务的请求看起来像一个数字ID的向量ids: Vec<u64>。对于ids中的每个id,我的服务必须从连续存储在SSD上的一长串记录中读取第id条记录。因为所有记录的大小RECORD_SIZE相同(实际上大约为6 KB),则每条记录的位置都是完全可预测的,因此简单的解决方案简化为

for id in ids {
   file.seek(SeekFrom::Start(id * RECORD_SIZE)).unwrap();
   let mut record = vec![0u8; RECORD_SIZE];
   file.read_exact(&mut record).unwrap();

   records.push(record);
}

// Do something with `records`

现在,可悲的是,以下情况适用:

  • ids的元素是不连续的、不可预测的、非结构化的,并且有效地等效于在[0, N]范围内均匀随机分布。
  • N太大了,我无法将整个文件存储在内存中。
  • ids.len()N小得多,因此如果不将99%的读取用于与ids无关的记录,我就无法高效地线性循环文件。

现在,阅读规格,我的SSD的原始QD 32 IOPS应该允许我及时收集所有记录(即,在下一个请求到来之前)。但是,我观察到我的琐碎实现要糟糕得多。我怀疑这是由于它实际上是一个QD 1实现:

  • 从磁盘的随机位置读取某些内容。
  • 等待数据到达,将其存储在RAM中。
  • 从磁盘的另一个独立位置读取下一个内容。

现在,问题是我一开始就知道所有的ids,如果有一种方法可以指定,我会很高兴:

  • 尽可能并行地读取与ids的每个元素相关的所有位置。
  • 当这件事完成后,继续做每件事。

我想知道在Rust中是否有一种简单的方法来完成这一点。我在标准库中寻找类似file.parallel_read的函数,在www.example.com上寻找有用的板条crates.io,但都无济于事。这让我很困惑,因为这应该是服务器/数据库设置中相对常见的问题。我错过了什么吗?

amrnrhlw

amrnrhlw1#

根据您的目标体系结构,posix_fadvise系统调用如下:
程序可以使用posix_fadvise()来声明将来要以特定模式访问文件数据的意图,从而允许内核执行适当的优化。
你可以传递偏移量RECORD_SIZE,可能还有POSIX_FADV_WILLNEED通知。函数和常量都在libc机箱中可用。同样的想法可以通过使用posix_madvise()POSIX_MADV_WILLNEED的内存Map文件来实现,正如注解中所暗示的那样。
然后你需要做一些性能调整来决定提前多少时间调用这些函数。如果不够早,数据就不会在你需要的时候出现,太早意味着你不必要地增加了系统内存的压力。

相关问题