4

我有一个应用程序,它从磁盘中的单个对象加载 170 个文件(假设它们是文本文件)并一直保存在内存中。当我从磁盘加载这些文件时,内存被分配一次。因此,不涉及内存碎片。我还使用 FastMM 来确保我的应用程序永远不会泄漏内存。

该应用程序将所有这些文件相互比较以找到相似之处。过度简化我们可以说我们比较文本字符串,但算法要复杂得多,因为我必须允许字符串之间存在一些差异。每个文件大约 300KB。加载到内存(保存它的对象)中需要大约 0.4MB 的 RAM。因此,正在运行的应用程序需要大约 60MB 或 RAM(工作集)。它处理数据大约 15 分钟。问题是它会产生超过 4000 万个页面错误。

为什么?我有大约 2GB 的可用 RAM。据我所知,页面错误很慢。他们在多大程度上减慢了我的程序?如何优化程序以减少这些页面错误?我想这与数据局部性有关。有人知道这个(Delphi)的一些示例算法吗?

更新:
但是看看页面错误的数量(任务管理器中没有其他应用程序接近我,甚至到目前为止)我想如果我设法优化内存布局(减少页面错误)我可以提高我的应用程序的速度)。


Delphi 7,Win 7 32 位,RAM 4GB(3GB 可见,2GB 免费)。

4

3 回答 3

3

警告 - 我只是解决页面错误问题。

我不能确定,但​​您是否考虑过使用内存映射文件?这样,windows 将使用文件本身作为分页文件(而不是主分页文件 pagrefile.sys)。如果文件是只读的,那么理论上页面错误的数量应该会减少,因为页面不需要通过页面文件写出到磁盘,因为 Windows 只会根据需要从文件本身加载数据。

现在,为了减少文件分页和分页,您需要尝试以一个方向浏览数据,以便在读取新数据时,可以永远丢弃旧页面。在这里,您需要权衡再次检查文件和缓存数据 - 缓存必须存储在某个地方。

请注意,内存映射文件是 Windows 加载 .dll 和 .exe 的方式。我已经用它们扫描了千兆字节的文件而没有达到内存限制(那时我们有 MB,而不是 GB 的 ram)。

但是,根据您描述的数据,我建议不返回 ovver 文件的能力将减少重新分页的数量。

于 2010-10-15T11:53:22.743 回答
1

在我的机器上,开发人员工作室报告了大多数页面错误,据报道在总 CPU 时间超过 30 分钟后有 4M 页面错误。在一半的时间内,您可以获得 10 倍的收益。而且我的系统内存不足。所以40M的故障似乎很多。

可能只是你有内存泄漏。

工作集只是您的应用程序正在使用的物理内存。如果您泄漏内存并且不触摸它,它将被分页。您将看到虚拟内存使用(或页面文件使用)增加。当堆内存遍历堆时,这些页面可能会被换回,以再次被窗口换出。

因为你有很多 RAM,换出的页面将保留在物理内存中,因为没有其他人需要它们。(从 RAM 恢复的页面算作软故障,从磁盘恢复的算作硬故障)

于 2010-10-15T12:57:29.930 回答
0

您是否使用指数调整大小系统?

如果你在加载时以太小的增量增长内存块,它可能会不断地从系统请求大块,复制数据,然后释放旧块(假设 fastmm(de)直接从操作系统分配非常大的块)。

也许这会以某种方式导致操作系统从您的应用程序进程中释放内存然后再次添加它的循环,从而导致第一次写入时出现页面错误。

还要避免对非常大的文件使用 Tstringlist.load* 方法,IIRC 这些消耗的空间是所需空间的两倍。

于 2010-10-15T18:25:59.230 回答