【问题标题】:How do I workaround heap fragmentation in a C++ server program?如何解决 C++ 服务器程序中的堆碎片问题?
【发布时间】:2010-12-08 05:55:08
【问题描述】:

堆碎片可能会导致预计会连续运行数月的服务器应用程序突然开始出现故障,以为内存不足。

假设我已尽最大努力将我的 VC++ 服务器应用程序中的运行时堆碎片最小化,但它仍然会累积并导致问题。例如,我可以每月或每处理 50 万个请求自动重新启动应用程序 - 安全地停止它并安全地重新启动一个新堆。对于解决方法堆碎片,我还能做些什么?

【问题讨论】:

    标签: c++ visual-c++ memory heap-fragmentation


    【解决方案1】:

    与此处相同的答案:How to detect and estimate heap fragmentation in my C++ program?

    编写适合您的内存分配模式的自己的内存管理器。或者购买一个(例如智能堆)。

    由于碎片取决于您的内存分配模式/释放模式,因此很难给出更好的答案。但是您可以查看固定大小的分配器或查看smart heap page 它们如何处理分配。也有很多关于这个主题的论文。例如www.memorymanagement.org

    或者你可以看看FastMM4——它是开源的,但是在 Pascal/Delphi 中

    还有一些编程技巧。最值得注意的是:Object Pool。在这种情况下,没有碎片,因为对象被重复使用而不是被释放。但我认为固定大小的分配器比对象池执行得更好。以这种方式使用的对象池只是一个“可怜的”固定大小分配器。

    【讨论】:

    • 这些是减少碎片的好方法,但不是解决问题的方法。
    • 我假设 sharptooth 会询问如果他的程序检测到堆碎片该怎么办。
    • 是的,没错。一种策略是定期重启。我还能做什么?
    • 防止堆碎片。否则:尽可能多地释放内存,然后重新分配。尝试释放靠近的内存区域。
    【解决方案2】:

    您可以检查堆以查看碎片何时达到某个级别,而最大的连续内存块低于某个级别 - 毕竟 - 您将开始当不是所有内存都用完,而是当您尝试分配大于堆中最大可用连续空间大小的对象时,才能查看内存不足错误。

    您可以使用VirtualQueryEx 遍历您的堆并找到最大的空闲连续区域。有关如何执行此操作的示例,请参阅this article

    【讨论】:

      【解决方案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 的服务包中引入的,但在 Windows Vista 之前必须主动启用。

      有一个工具vmmap 可以轻松概述内存,并在发生碎片时提供很好的概述。

      【讨论】:

      • VMMap 是一个很棒的发现。谢谢。
      • 注意,上面的代码有两个错误! 1、nheaps可以大于1023,那么就有可能发生访问冲突。阅读 GetProcessHeaps 上的 MSDN。首先像这样调用它: GetProcessHeaps(0,NULL) 以获取堆计数,然后分配适当的缓冲区。 2. MSDN 明确指出您应该仅将 GetProcessHeaps 结果用于调试目的。因此,一旦您获得了堆,它们可能已经被更改(即关闭)。使用此类句柄是未定义的行为...
      【解决方案4】:

      显而易见的解决方法是挖掘过去发明的旧解决方案。例如,可移动对象的不透明句柄而不是原始指针。这允许您对堆进行碎片整理。

      【讨论】:

      • 这就是 Apple 的 Mac 能够在 128k 内存中运行整个 Windowed 操作系统和应用程序的方式。这在今天看来是不可能的。
      猜你喜欢
      • 1970-01-01
      • 2012-04-03
      • 2021-07-23
      • 1970-01-01
      • 2010-09-08
      • 2015-03-31
      • 2014-07-01
      • 2010-12-08
      • 2020-09-01
      相关资源
      最近更新 更多