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