动态阵列存储器分配策略

时间:2015-02-16 17:17:02

标签: delphi

我使用动态数组编写了一个32位程序来存储未知计数的三角形列表。我目前的策略是估计非常多的三角形,然后在创建所有三角形时修剪列表。在某些情况下,我只会在其他情况下分配一次内存,我需要添加到分配中。

对于一个非常大的数据集,当我的应用程序内存使用量大约为1.2GB时,我的内存不足,而且由于分配步骤太大,我觉得我可能会破坏内存。

看看FastMM(内存管理器)我看到这些常量会建议其中一个是增量的好大小。

ChunkSize = 64 * 1024;
MaximumSmallBlockSize = 32752;
LargeBlockGranularity = 64 * 1024;

其中一个是增加阵列大小的最佳尺寸吗?

最终这个程序会变成64位,但我们还没有为这一步做好准备。

2 个答案:

答案 0 :(得分:6)

这里真正的问题不在于你的内存不足,而是内存分配器无法找到足够大的连续地址空间块。您可以做的一些简单的事情包括:

  1. 以64位进程执行代码。
  2. 添加LARGEADDRESSAWARE PE标志,以便您的进程获得4GB的地址空间而不是2GB。
  3. 除此之外,您可以做的最好的事情是分配较小的块,以避免将大型数据结构存储在连续内存中的要求。以块为单位分配内存。因此,如果您需要1GB内存,请分配64个大小为16MB的块。您使用的确切块大小可以根据您的需要进行调整。较大的块会带来更好的分配性能,但较小的块允许您使用更多的地址空间。

    将其包装在一个容器中,该容器向消费者提供类似接口的数组,但在内部将内存存储在非连续的块中。

答案 1 :(得分:4)

据我所知,Delphi中的动态数组使用连续的地址空间(至少在虚拟内存地址空间中)。

由于1.2 gb的内存不足,我想这就是内存管理器无法找到足够大的块连续内存以适应更大的阵列。

你可以解决这个限制的一种方法是将你的数组实现为一个较小的数组(比如说)200 mb的集合。在你达到记忆上限之前,这应该给你更多的空间。

从1.2 gb值,我猜你的程序没有被编译为"大地址识别"。您可以看到here如何编译您的应用程序。

最后一个技巧是将数组数据实际保存在文件中。我在我的应用程序中使用此技巧,我需要加载几GB图像以在网格中显示。我所做的是创建一个具有属性FILE_ATTRIBUTE_TEMPORARY和FILE_FLAG_DELETE_ON_CLOSE的文件,并从结果文件中保存/加载图像。来自CreateFile文档:

  

正在使用文件进行临时存储。文件系统避免写入   如果有足够的高速缓存,则数据返回大容量存储器,   因为应用程序在句柄后删除临时文件   关闭。在这种情况下,系统可以完全避免写入数据。   否则,在句柄关闭后写入数据。

由于它使用了高速缓冲存储器,我相信它允许应用程序使用超过32位限制的存储器,因为高速缓存由OS管理,并且(据我所知)未映射到进程内部'虚拟内存空间。在做这个改变之后,性能仍然相当不错。但我不能说演出是否仍然足以满足你的需求。