我遇到以下问题。一堆数据分成10k个小文件(每个大约8-16kib)。根据用户输入,我必须尽可能快地加载并处理它们。更确切地说,每个数据包可以分成100-100k个文件,并且大约有1k个数据包。虽然他们大多数是较小的。从单个文件并行读取
现在,我正在使用一个线程池,并在每个文件访问上,下一个空闲线程打开文件,读取它并返回准备显示的数据。随着未来文件数量的增长,我对这种方法并不感到满意,特别是如果它最终可能有大约100k或更多的文件(部署这肯定会很有趣)。
所以,这个想法是将所有这些小文件合并成一个大数据包,并从中读取。我可以保证它将是只读的,但是我不知道预先并发访问一个文件的线程数(我知道最大数目)。这会给我大约1000个大小适中的文件,并且我可以轻松添加新的数据包。
问题是:在这种情况下,如何让1..N个线程从单个文件中有效读取?我可以在Windows上使用异步I/O,但对于小于64k的读取,它应该是同步的。内存映射文件不是一种选择,因为预期的大小大于1.6吉比特,我仍然需要能够在x86上运行(除非我能够有效地映射一些小部分,读取它,再次取消映射 - 我的经验内存映射是它比一次读取带来了相当多的开销)。
我想过打开每个数据包N次,并给每个线程一个循环方式的句柄,但问题是,它可以以(数据文件数)x(最大数量线程)打开句柄(可以很容易地变成8-16k),并且我必须在每次访问数据包时使用同步,或者使用一些无锁魔术来获得下一个空闲文件句柄。因为这似乎不是一个原始问题(我猜,任何数据库引擎都有类似的问题,在这里你可以有N行(文件在我的情况下)的M个表(数据包),并且你想要允许尽可能多的线程同时读取行)。那么这里推荐的做法是什么?顺便说一下,它应该在Windows和Linux上运行,所以欢迎使用可移植的方法(或者至少可以在两种平台上工作的方法,即使它们使用不同的底层API--只要它们可以被包装,我很高兴)。
[编辑]这不是关于速度,这是关于隐藏延迟。也就是说,我可能每秒钟读取100个这样的小文件,所以我最多只能达到1 mib/s。我主要关心的是寻找时间(因为我的访问模式不可预测),并且我想隐藏它们,通过在向用户显示旧数据的同时开始读取。问题是如何让几个线程通过几个文件发出IO请求,可能有> 1个线程访问单个文件。
如果其中一个调用需要70 ms左右才能完成,那真的没有问题,但如果读取调用阻塞,我无法负担得起。
您的数据是否存储在RAID阵列或类似的东西上? – Egwor 2009-05-03 09:58:31
不,完全没有。同样,速度不是主要问题,只要它是异步运行的,即使每次读取都需要100 ms,我也可以。问题是如何让多个线程同时访问一个文件:) – Anteru 2009-05-03 10:01:46
我看到映射整个文件集的内存不是一个选项,但也许你可以使用一块内存作为访问文件的大缓存大多数时候(或者它们全部只能被读取一次?) – schnaader 2009-05-03 10:02:25