替代减少从硬盘读取访问时间的大量二进制文件

时间:2012-12-17 18:52:25

标签: c database-design

在我的第一个应用程序原型中,我必须从硬盘顺序读取大约400,000个文件(每个4KB文件,大约总共1.5 GB数据),并对从每个文件读取的数据执行一些操作,并将结果存储在内存。通过这种机制,我首先访问文件的I / O然后利用CPU进行操作,并继续使用另一个文件,但这是一个非常缓慢的过程。

要解决此问题,现在我们首先读取所有文件,并将所有文件数据存储在RAM中,然后进行操作(利用CPU)。它取得了显着的进步。

但在我的第二阶段开发中,我必须读取20 GB的数据,现在我无法存储在RAM中。而且,CPU利用率的单次读取操作非常耗时。

有人可以建议一些方法来解决这个问题吗?

我正在使用Visual Studio编译器在Windows上用Windows开发此应用程序。

3 个答案:

答案 0 :(得分:4)

有一种称为异步I / O(AIO)的技术,可让您在后台读取文件时继续对CPU进行一些处理。您可以使用它在处理文件的同时读取下几个文件。

各种AIO调用都是特定于操作系统的。在Windows上,Microsoft将其称为“重叠I / O”。有关详细信息,请参阅this Wikipedia pagethis MSDN page

答案 1 :(得分:1)

  

要解决此问题,现在我们首先读取所有文件,并将所有文件数据存储在RAM中,然后进行操作(利用CPU)。

(假设文件可以独立处理......)

你在中途。而不是等到所有文件都加载到RAM后,只要加载任何文件就开始处理。这将是pipelining的一种形式。

您需要三个组件:

  1. 读取文件(“生产者”)的线程 1
  2. 处理文件(“消费者”)的线程 2
  3. 它们之间的消息队列 3
  4. 生产者以你已经在做的方式读取文件,但不是处理它们,而是将它们排入消息队列。消费者线程等待,直到它可以从队列中取出文件,处理它,然后立即释放文件占用的内存并继续等待队列。

    如果您可以通过从头到尾顺序遍历文件来处理文件,您甚至可以设计更精细的“流式传输”,其中文件将以块的形式读取和处理,这可以降低峰值内存消耗甚至更多(例如,如果你有一些超大文件,不再需要将整个保存在内存中)。


    1 或者一组并行化I / O的线程,如果您预计从多个物理磁盘读取。

    2 或者一组线程使CPU核心饱和,如果处理文件并不比读取文件便宜。

    3 您不需要花哨的持久分布式消息队列。只是一个 直接内存中队列,.NET中的a-la BlockingCollection(我相信你会发现类似纯C的东西)。

答案 2 :(得分:0)

  1. 创建将文件读入RAM的线程(循环中)。
  2. 处理后,在单独的线程[s]和空闲RAM中处理RAM中的数据。
  3. 对受互斥锁保护的共享对象中的文件(已读取和已处理)的记录进行限制和轮询。
  4. 将信号量用于资源(RAM中的文件)生产/利用率同步。