从磁盘读取10 GB文件的最快方法是什么?

时间:2009-08-28 22:03:41

标签: perl io mmap performance

我们需要读取和计算不同类型的消息/运行 关于10 GB文本文件的一些统计信息,例如FIX引擎 登录。我们使用Linux,32位,4个CPU,Intel,在Perl编码但是 语言并不重要。

我在Tim Bray中找到了一些有趣的提示 WideFinder project。但是,我们发现使用内存映射 本质上受到32位架构的限制。

我们尝试使用多个进程,这似乎有效 如果我们使用4个进程并行处理文件会更快 在4个CPU上。添加多线程可能会减慢速度 因为上下文切换的成本。我们尝试过改变 线程池的大小,但仍然比 简单的多进程版本。

内存映射部分不是很稳定,有时候也是如此 在2 GB文件上花费80秒,有时7秒,可能来自 页面错误或与虚拟内存使用相关的内容。 无论如何,Mmap在32位上不能超过4 GB 架构。

我们尝试了Perl的IPC::MmapSys::Mmap。看着 进入Map-Reduce,但问题实际上是I / O. 绑定,处理本身足够快。

因此我们决定尝试通过调优来优化基本I / O. 缓冲大小,类型等

任何知道现有项目的人都可以 在任何语言/平台上都能有效地解决问题 指向一个有用的链接或建议一个方向?

13 个答案:

答案 0 :(得分:9)

大多数情况下,I / O绑定不受CPU限制,因此只需通过普通的Perl I / O读取此文件并在单线程中处理它。除非您证明您可以执行比单CPU工作更多的I / O,否则不要浪费您的时间。无论如何,你应该问:为什么地球上这是一个巨大的文件?为什么地球上的它们在产生它时会以合理的方式分裂它?这将是更值得的工作。然后你可以将它放在单独的I / O通道中并使用更多的CPU(如果你不使用某种RAID 0或NAS或......)。

测量,不要假设。不要忘记在每次测试之前刷新缓存。请记住,序列化I / O比随机速度快。

答案 1 :(得分:4)

这一切都取决于您可以做什么样的预处理以及何时进行。 在我们拥有的一些系统上,我们将这些大型文本文件gzip,将它们缩小到原始大小的1/5到1/7。使这成为可能的部分原因是我们不需要处理这些文件 在它们被创建之后几个小时,并且在创建时我们在机器上没有任何其他负载。

处理它们或多或少是以zcat那些文件的方式完成的我们正在处理。(尽管使用定制的zcat,它已经完成了unix套接字)。它交换磁盘i / o时间的CPU时间,并且我们的系统值得。有很多变量可以使这个特定系统的设计非常糟糕。

答案 2 :(得分:3)

也许你已经阅读过这个论坛帖子,但如果没有:

http://www.perlmonks.org/?node_id=512221

它描述了使用Perl逐行进行,并且用户似乎认为Perl非常有能力。

哦,是否可以从RAID阵列处理文件?如果您有多个镜像磁盘,则可以提高读取速度。磁盘资源的竞争可能会使您的多线程尝试无效。

祝你好运。

答案 3 :(得分:3)

我希望我对你文件的内容有更多的了解,但除了它是文本之外我不知道,这听起来像是一个很好的MapReduce问题。

PS,任何文件的最快读取都是线性读取。 cat file > /dev/null应该是可以读取文件的速度。

答案 4 :(得分:2)

您是否考虑过流式传输文件并过滤掉辅助文件以获得任何有趣的结果? (重复,直到你有一个可管理的大小文件)。

答案 5 :(得分:1)

基本上需要“分而治之”,如果你有一个计算机网络,那么将10G文件复制到尽可能多的客户端PC,让每个客户端PC读取文件的偏移量。为了获得额外的好处,除了分布式阅读之外,还要让EACH pc实现多线程。

答案 6 :(得分:1)

解析文件一次,逐行阅读。将结果放在一个像样的数据库中的表中。根据需要运行尽可能多的查询。定期用新输入的数据喂养野兽。

意识到操纵10 Gb文件,将其传输到(即使是本地)网络,探索复杂的解决方案等都需要时间。

答案 7 :(得分:1)

我有一位同事通过访问64位Linux来加速他的FIX阅读。如果这是件值得的东西,可以花点钱买一些更好的硬件。

答案 8 :(得分:1)

嗯,但是C中的read()命令有什么问题?通常有2GB的限制, 所以只需按顺序调用它5次。那应该相当快。

答案 9 :(得分:1)

如果您受I / O限制并且您的文件位于单个磁盘上,则没有太多事情可做。跨整个文件进行简单的单线程线性扫描是从磁盘上获取数据的最快方法。使用大缓冲区大小可能会有所帮助。

如果你可以说服文件的编写者在多个磁盘/机器上对其进行条带化,那么你可以考虑对阅读器进行多线程处理(每个读取头一个线程,每个线程从一个条带读取数据)。

答案 10 :(得分:1)

既然你说平台和语言无关紧要......

如果您希望获得与源介质允许的速度一样快的稳定性能,我知道这可以在Windows上完成的唯一方法是通过重叠的非OS缓冲对齐顺序读取。您可以使用两个或三个缓冲区获得一些GB / s,除此之外,在某些时候您需要一个环形缓冲区(一个写入器,1个以上读取器)以避免任何复制。确切的实现取决于驱动程序/ API。如果在处理IO的线程(内核和用户模式)上都有任何内存复制,显然要复制的缓冲区越多,浪费的时间就越多,而不是IO。因此,最佳缓冲区大小取决于固件和驱动程序。在Windows上,要尝试的好值是磁盘IO的32 KB的倍数。 Windows文件缓冲,内存映射和所有这些东西增加了开销。只有以随机访问方式进行相同数据的多次读取(或两者)才有好处。因此,对于一次按顺序读取大文件,您不希望操作系统缓冲任何内容或执行任何memcpy。如果使用C#,由于编组而调用操作系统也会受到惩罚,因此除非使用C ++ / CLI,否则互操作代码可能需要一些优化。

有些人更喜欢将硬件投入到问题中,但如果你有更多的时间而不是金钱,在某些情况下,可以优化一台消费者在一台消费者级别的计算机上执行100-1000倍的计算机。原因是如果处理对延迟敏感,那么超出使用两个核心可能会增加延迟。这就是为什么驱动程序可以推动千兆字节/秒,而企业软件在完成所有操作时终止为兆字节/秒。无论报告,业务逻辑和企业软件做什么,也可能在两个核心消费者CPU上以千兆字节/秒的速度完成,如果写得像你回到80年代写游戏一样。我听说过以这种方式接近其整个业务逻辑的最着名的例子是LMAX外汇交易所,它发布了一些基于环形缓冲区的代码,据说受到网卡驱动程序的启发。

忘记所有的理论,如果你对< 1 GB / s,Windows上的一个可能的起点我发现从winimage查看readfile源,除非你想深入研究sdk / driver样本。可能需要一些源代码修复才能在SSD速度下正确计算性能。也尝试使用缓冲区大小。 具有最佳缓冲区大小的开关/ h多线程和/或重叠(完成端口)IO(尝试32,64,128 KB等)在我的经验中没有使用Windows文件缓冲,在从SSD(冷数据)读取时同时处理时提供最佳性能(使用/ a进行Adler处理,否则它太受CPU限制了。)

答案 11 :(得分:0)

我好像回想起我们正在阅读大文件的项目,我们的实现使用多线程 - 基本上n * worker_threads开始增加文件的偏移量(0,chunk_size,2xchunk_size,3x chunk_size ... n-1x chunk_size并且正在阅读较小的信息块。我不能完全回想起我们对此的推理,因为其他人正在设计整个事情 - 工人不是唯一的事情,但这大致就是我们做的事情。

希望有所帮助

答案 12 :(得分:0)

在序列无关紧要的问题中没有说明。所以, 将文件分成相等的部分,每个1GB,并且因为你使用多个CPU,所以多个线程不会成为问题,所以使用单独的线程读取每个文件,并使用容量的RAM> 10 GB,然后所有内容都将存储在由多个线程读取的RAM中。