我需要编写一些代码(用任何语言)来处理驻留在本地Linux文件系统上的10,000个文件。每个文件大小约为500KB,由固定大小的4KB记录组成。
每条记录的处理时间可以忽略不计,并且可以在不同文件内和跨文件的任何顺序处理记录。
一个天真的实现将以任意顺序逐个读取文件。但是,由于我的磁盘读取速度非常快,但搜索速度很慢,这几乎肯定会产生受磁盘搜索限制的代码。
有没有办法对读数进行编码,使其受磁盘吞吐量的限制,而不是寻找时间?
一个问题是尝试大致了解文件在磁盘上的位置,并使用它来对读取进行排序。但是,我不确定可以使用哪种API。
我当然愿意接受任何其他想法。
文件系统是ext4,但这是可以协商的。
答案 0 :(得分:6)
也许您可以通过aio_read快速连续安排所有这些内容来完成阅读。这会将所有读取一次放入文件系统读取队列,然后文件系统实现可以以最小化搜索的方式完成读取。
答案 1 :(得分:2)
一种非常简单的方法,但没有保证结果。尽可能多地打开所有文件并一次读取所有文件 - 使用线程或异步I / O.这样磁盘调度程序就知道你读了什么,并且可以自己减少搜索。 编辑 wildplasser 观察到,并行open()
可能只能使用线程,而不是异步I / O.
另一种方法是尝试自己做重物。不幸的是,这涉及一个困难的步骤 - 获取文件到物理块的映射。没有标准接口可以执行此操作,您可以从ext2fsprogs或内核FS驱动程序中提取逻辑。这涉及到读取已安装文件系统底层的物理设备,在您尝试获取一致快照的同时可以写入它。
获得物理块后,只需对它们进行排序,将映射反转回文件偏移量,然后按物理块顺序执行读取。
答案 2 :(得分:1)
你能推荐使用SSD作为文件存储吗?因为无法移动,所以应该大大减少寻道时间。
答案 3 :(得分:0)
由于操作类似且数据是独立的,因此您可以尝试使用线程池来提交可处理多个文件的作业(可以是单个文件)。然后,您可以让一个空闲线程完成一个作业。这可能有助于将IO操作与执行重叠。
答案 4 :(得分:0)
一种简单的方法是保留原始程序,但是分叉一个额外的进程,除了预取文件之外没有其他任务,并填充磁盘缓冲区缓存。 (unix / linux系统使用所有“空闲”内存作为磁盘缓冲区)。
主要任务将保留一些文件(比如说十个)。困难的部分是保持同步。管道似乎是实现这一目标的明显方法。
更新:
主要过程的伪代码:
对于奴隶进程:
对于队列,消息队列似乎最合适,因为它维护消息边界。另一种方法是每个子节点有一个管道(在fork()的情况下)或使用互斥体(当使用线程时)。
您需要近似seektime_per_file / processing_time_per_file工作线程/进程。
作为简化:如果不需要寻找文件(仅限顺序访问),则从属进程可以包含等效的
dd if=name bs=500K
,可以包装成popen()或pipe + fork()。