在虚拟内存系统上,虚拟地址空间意味着虚拟页面可以映射到任何地方。您不需要大量连续的物理内存块。如果您的虚拟地址空间碎片存在问题,那么您可能需要不同的内存管理策略。
但是,大多数选项都需要您的应用程序代码在某个级别上了解内存管理策略。我不相信这个问题有一个快速的解决方法 - 你可能需要进行合理的大手术来解决这个问题。这些选项都不易实现,您将不得不找到最适合您的特定情况的选项。
我可以看到的主要选项是:自定义内存分配器,涉及AWE的内容(请参见下文)或重新构建应用程序内的内存分配策略。
选项1:自定义的内存分配
定制存储器分配器不在C和C++界少见。你可能能够实现类似的东西。两种可能性都向你敞开:
构建了一个机制内存分配试图相邻空闲块合并成一个更大的块(可以为试图从失败的内存分配中恢复的一部分运行此)。这可能允许您透明地管理内存,而无需应用程序注意。实现这一点将是狡猾和技术性的,但可能是可行的。
这种方法的主要优点是它是唯一不需要您更改现有应用程序代码的方法。缺点是不能保证工作;合并操作仍有可能无法合并足够大的内存块来完成请求。合并操作在运行时也可能会在应用程序响应中造成重大暂停。
您可能需要以允许数据结构被压缩的方式构建应用程序。这将需要您维护支持要移动对象的句柄,即双重间接机制。我猜测可能有一个或相当少数不同的数据结构会导致这种碎片问题,所以它可能会本地化应用程序中的任何重新架构工作。
选项2:PAE
Windows不支持设施直接操作MMU,有几个可能的地方,这可能适用于您的应用程序。这绝对需要您的应用程序提供明确的体系结构支持,但它提供了使用比2GB大得多的内存池的可能性。
在Windows的服务器版本上,查看API's支持的PAE,它允许您手动操作系统的MMU并重新映射内存块。在两种方式之一
然而,这种方法需要您重新设计应用程序,以便对象的引用有足够的信息来管理显性换入过程中(可能是某类覆盖管理与一个代理机构的对象是通过这个系统引用)。这意味着涉及PAE的任何解决方案都不是FastMM的直接替代方案 - 您必须修改应用程序以明确支持PAE。
但是,这种代理机制可能意味着此子系统对客户端可能相对透明。除了管理间接和覆盖(这可能是也可能不是重要问题)的开销之外,代理可能实际上与原始API无法区分。这种类型的方法对于相对较少数量的大型重量级对象来说效果最佳,并且互连最少 - 标准应用程序是磁盘缓存。代理将不得不保持在内存中的固定位置,通过覆盖机制访问更大的对象。因人而异。
方案3:在源
一种可能性是你的对象分配策略可以从应用程序代码内优化(可能是从散装分配对象的池修复问题,然后从应用程序内管理)。这可能允许您在应用程序中处理内存碎片,而不尝试重写内存管理器。
此方法意味着您将不得不重新构建应用程序的某些部分,并且该方法的适用性实际上取决于应用程序的性质。只有你可以成为判断这可能工作得如何。
小改正:在64位操作系统版本上,为32位进程获得完整的4 GB地址范围。该进程可能无法使用它(由于在内存管理例程中使用了签名数据类型),但限制与在32位操作系统上不同。 AFAIR Delphi *确实有问题。 – mghie
是的,delphi在RTL中使用了很多有符号值的值 –