在阅读许多小文件时减​​少寻道时间

时间:2012-03-23 13:12:36

标签: linux language-agnostic filesystems

我需要编写一些代码(用任何语言)来处理驻留在本地Linux文件系统上的10,000个文件。每个文件大小约为500KB,由固定大小的4KB记录组成。

每条记录的处理时间可以忽略不计,并且可以在不同文件内和跨文件的任何顺序处理记录。

一个天真的实现将以任意顺序逐个读取文件。但是,由于我的磁盘读取速度非常快,但搜索速度很慢,这几乎肯定会产生受磁盘搜索限制的代码。

有没有办法对读数进行编码,使其受磁盘吞吐量的限制,而不是寻找时间?

一个问题是尝试大致了解文件在磁盘上的位置,并使用它来对读取进行排序。但是,我不确定可以使用哪种API。

我当然愿意接受任何其他想法。

文件系统是ext4,但这是可以协商的。

5 个答案:

答案 0 :(得分:6)

也许您可以通过aio_read快速连续安排所有这些内容来完成阅读。这会将所有读取一次放入文件系统读取队列,然后文件系统实现可以以最小化搜索的方式完成读取。

答案 1 :(得分:2)

一种非常简单的方法,但没有保证结果。尽可能多地打开所有文件并一次读取所有文件 - 使用线程或异步I / O.这样磁盘调度程序就知道你读了什么,并且可以自己减少搜索。 编辑 wildplasser 观察到,并行open()可能只能使用线程,而不是异步I / O.

另一种方法是尝试自己做重物。不幸的是,这涉及一个困难的步骤 - 获取文件到物理块的映射。没有标准接口可以执行此操作,您可以从ext2fsprogs或内核FS驱动程序中提取逻辑。这涉及到读取已安装文件系统底层的物理设备,在您尝试获取一致快照的同时可以写入它。

获得物理块后,只需对它们进行排序,将映射反转回文件偏移量,然后按物理块顺序执行读取。

答案 2 :(得分:1)

你能推荐使用SSD作为文件存储吗?因为无法移动,所以应该大大减少寻道时间。

答案 3 :(得分:0)

由于操作类似且数据是独立的,因此您可以尝试使用线程池来提交可处理多个文件的作业(可以是单个文件)。然后,您可以让一个空闲线程完成一个作业。这可能有助于将IO操作与执行重叠。

答案 4 :(得分:0)

一种简单的方法是保留原始程序,但是分叉​​一个额外的进程,除了预取文件之外没有其他任务,并填充磁盘缓冲区缓存。 (unix / linux系统使用所有“空闲”内存作为磁盘缓冲区)。

主要任务将保留一些文件(比如说十个)。困难的部分是保持同步。管道似乎是实现这一目标的明显方法。

更新:

主要过程的伪代码:

    • 从工作清单中提取文件名
    • 如果空goto 2。
    • (可能)分叉工作进程或线程
    • 添加到预取队列
    • 添加到内部队列
    • 如果内部队列上的项目少于XXX项goto 1
    • 从内部队列中提取文件名
    • 处理它
    • 转到1
  1. 对于奴隶进程:

    • 从队列中提取
    • 如果为空:退出
    • 预取文件
    • 循环或退出

    对于队列,消息队列似乎最合适,因为它维护消息边界。另一种方法是每个子节点有一个管道(在fork()的情况下)或使用互斥体(当使用线程时)。

    您需要近似seektime_per_file / processing_time_per_file工作线程/进程。

    作为简化:如果不需要寻找文件(仅限顺序访问),则从属进程可以包含等效的

    dd if=name bs=500K
    

    ,可以包装成popen()或pipe + fork()。