堆碎片可能导致服务器应用程序连续运行数月以突然开始出现故障,认为内存不足。
让我们假设我已尽最大努力减少VC ++服务器应用程序中的运行时堆碎片,但它仍然会累积并导致问题。例如,我可以每月自动重启应用程序或每处理50万个请求 - 安全地停止它并安全地重新启动新堆。我还可以对解决方法堆碎片做些什么?
答案 0 :(得分:3)
与此处相同的答案:How to detect and estimate heap fragmentation in my C++ program?
编写适合您的内存分配模式的内存管理器。或者购买一个(例如智能堆)。
由于碎片取决于您的内存分配模式/释放模式,因此难以给出更好的答案。但是您可以查看固定大小的分配器,或者查看smart heap page它们如何处理分配。关于这个主题也有很多论文。试试例如www.memorymanagement.org
或者您可以查看FastMM4 - 这是开源的,但是在Pascal / Delphi中
也有一些编程技巧。最值得注意的是:Object Pool。在这种情况下,没有碎片,因为对象被重用而没有被释放。但我认为固定大小的分配器比对象池表现更好。这种方式使用的对象池只是一个“穷人”固定大小的分配器。
答案 1 :(得分:3)
一个好的起点是启用低碎片堆并检查它仍然碎片的天气。
HANDLE heaps[1025];
DWORD nheaps = GetProcessHeaps((sizeof(heaps) / sizeof(HANDLE)) - 1, heaps);
for (DWORD i = 0; i < nheaps; ++i) {
ULONG enableLFH = 2;
HeapSetInformation(heaps[i], HeapCompatibilityInformation, &enableLFH, sizeof(enableLFH));
}
这个新推出的内存管理器默认在Vista / Server 2008上打开... 因此,如果您确定在较新的服务器操作系统上世界更好,这可能就是原因。
低碎片堆是在Windows 2000的Service Pack中引入的,但必须在Windows Vista之前启用它。
有一个工具vmmap可以简单地概述内存,并在发生碎片时提供一个很好的概述。
答案 2 :(得分:0)
不是根据请求的时间或数量来安排重启,而是可以检查堆,看看碎片何时达到最大连续内存块低于某个级别的水平 - 毕竟 - 你将开始当所有内存都用尽但你尝试分配大于堆中最大的自由连续空间大小的对象时,看看内存不足错误。
您可以使用VirtualQueryEx来堆积并找到最大的免费连续区域。有关如何执行此操作的示例,请参阅this article。
答案 3 :(得分:0)
明显的解决方法是挖掘过去发明的旧解决方案。例如,可移动对象的不透明句柄而不是原始指针。这允许您对堆进行碎片整理。