【问题标题】:Fastest way to read many 300 bytes chunks randomly by file offset from a 2TB file?通过 2TB 文件的文件偏移量随机读取许多 300 字节块的最快方法?
【发布时间】:2012-01-17 16:04:11
【问题描述】:

我在 RAID 5 (4 x 7.2k @ 3TB) 系统上有一些 2TB 只读(一旦创建就不会写入)文件。

现在我有一些线程想要读取该文件的某些部分。 每个线程都有一个它需要的块数组。 每个块都由要读取的文件偏移量(位置)和大小(大部分约为 300 字节)寻址。

读取此数据的最快方法是什么。 我不关心 CPU 周期,(磁盘)延迟才是最重要的。 因此,如果可能的话,我想利用硬盘的 NCQ。

由于文件被高度压缩并且会随机访问并且我确切地知道位置,我没有其他方法来优化它。

  • 我应该将文件读取集中到一个线程吗?
  • 我应该保持文件打开吗?
  • 是否应该每个线程(可能大约 30 个)同时打开每个文件,新线程(来自 Web 服务器)是什么情况?
  • 如果我等待 100 毫秒并按文件偏移量(最低优先)对读数进行排序,会有帮助吗?

读取数据的最佳方式是什么?您有经验、技巧、提示吗?

【问题讨论】:

    标签: c# .net file-io binary-data


    【解决方案1】:

    并行请求的最佳数量很大程度上取决于应用程序之外的因素(例如磁盘数=4、NCQ 深度=?、驱动程序队列深度=?...),因此您可能希望使用可以适应的系统或适应。我的建议是:

    • 将所有读取请求连同一些允许通知请求线程的元数据一起写入队列
    • 有 N 个线程从该队列中出列,同步读取块,通知请求线程
    • 使 N 运行时可更改
    • 由于 CPU 不是您关心的问题,您的工作线程可以计算浮动延迟平均值(和/或最大值,具体取决于您的需要)
    • 上下滑动 N,直到到达最佳位置

    为什么要同步读取?它们的延迟比异步读取低。 为什么要在队列上浪费延迟?一个好的无锁队列实现开始时延迟小于 10ns,远少于两个线程切换

    更新:一些问答

    读取线程是否应该保持文件打开? 是的,确实如此。

    您会将 FileStream 与 FileOptions.RandomAccess 一起使用吗? 是的

    你写“同步读取块”。这是否意味着每个读取线程都应该在将读取块的命令出队后立即开始从磁盘读取块? 是的,我就是这个意思。读取请求的队列深度由线程数管理。

    【讨论】:

    • 读取线程是否应该保持文件打开?我想是的。你会将 FileStream 与 FileOptions.RandomAccess 一起使用吗?你写“同步读取块”。这是否意味着每个读取线程都应该在将读取块的命令出队后立即开始从磁盘读取块?
    • 编辑了我的答案,试图回答你的评论。
    • 我忘了,你写道:“良好的无锁队列实现开始于小于 10ns 的延迟”。你有什么特别的课程/项目吗?
    • 我愿意:我写了一个,因为通常的怀疑没有扩展(甚至在简单的 8 核系统上也没有)。猜猜是时候开源它了。你会接受 LGPL 吗?这意味着在单独的 DLL 中使用 LocklessQueue,您可以在商业项目中使用它。
    • 酷,谢谢。是的,LGPL 没问题。我会弄乱一点,并在源代码中阅读您的 cmets。但是一个非常小的示例代码如何使用它对您的项目非常有用。好的,通过阅读源代码我认为可以自己看到它。
    【解决方案2】:

    磁盘是“单线程”的,因为只有一个磁头。无论您使用多少线程,它都不会更快......实际上更多的线程可能只会减慢速度。只需获取列表并在应用中对其进行排列(排序)即可。

    您当然可以使用多个线程,这可能会更有效地利用 NCQ,但将其安排在应用程序中并使用一个线程应该会更好。

    如果文件是碎片化的 - 使用 NCQ 和几个线程,因为您无法知道磁盘上的确切位置,因此只有 NCQ 可以优化读取。如果它是连续的 - 使用排序。

    您也可以尝试直接 I/O 以绕过操作系统缓存并按顺序读取整个文件...有时会更快,尤其是当您在此阵列上没有其他负载时。

    【讨论】:

    • -1 部分。如果您有多个线程,则多个请求会击中光盘。好的磁盘(SAS、SATA)允许磁盘重新排列它们以提高效率(“本机命令队列”)并以其他顺序提供结果。与普通同步单线程 IO 相比,这为您提供了显着的提升。
    • 另外我有raid 5。所以每个磁盘都可以从其他位置读取。
    • 此外,reuqested chunks 非常小,因此对于 RAID5 和大多数控制器一次读取完整条带,很可能另一个块已经在 RAM 中。
    【解决方案3】:

    ReadFileScatter 会做你想做的事吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-25
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-26
      相关资源
      最近更新 更多