【问题标题】:How much memory was actually allocated from heap for an object?实际上从堆中为对象分配了多少内存?
【发布时间】:2010-10-31 06:27:40
【问题描述】:

我有一个程序使用太多内存在堆上分配大量小对象。所以我想研究优化它的方法。该程序使用 Visual C++ 7 编译。

有没有办法确定给定对象实际分配了多少内存?我的意思是当我调用 new 时,堆会分配 不少于 必要的数量。我怎样才能知道到底分配了多少?

【问题讨论】:

  • 你在什么平台上运行?

标签: c++ visual-c++ memory memory-management


【解决方案1】:

没有确切的答案,因为一些堆管理器可能会使用不同数量的内存来进行相同大小的顺序分配。此外,(通常)没有直接的方法来测量特定分配占用的字节数。

您可以通过分配一定数量的相同大小的项目(例如,4096)并注意所用内存的差异来近似此值。将后者除以前者会给你答案。请注意,此值会随着操作系统、操作系统版本和操作系统版本的不同而变化,有时应用程序的调试版本可能会启用额外的堆跟踪,这会增加开销。在某些操作系统上,用户可以更改堆策略(即默认使用一个堆分配器与另一个堆分配器)。示例:Windows 和 pageheap.exe

仅供参考,Windows 32 位上的默认(不是 LFH)堆占用:

  • sizeof(your_type),四舍五入到 DWORD 边界,
  • 3 个指向 prev/next/size 的指针
  • 2 个安全 cookie 指针

【讨论】:

  • +1: ...有关 Windows 下分配的一些有趣信息。
【解决方案2】:

您可能正在寻求迁移到内存池模型(这是先前关于“分配大型池”的答案所描述的内容。由于内存池不需要每次分配的开销,它们可以节省大量空间小对象。如果一组小对象的生命周期很短(即你分配了一堆小对象然后需要摆脱很多),内存池也快得多,因为你可以直接释放池每个对象。

维基百科有一些关于该技术的信息以及一些实现的链接:

http://en.wikipedia.org/wiki/Memory_pool

您应该能够通过简单的网络搜索找到其他实现。

【讨论】:

    【解决方案3】:

    不一定以独立于平台的方式。我不记得任何手头的细节(除了我很确定你没有使用的操作系统),但你的操作系统可能会提供一种测试 malloc 分配的“大小”的方法,新的可能使用 malloc 或等效项。因此,您可能能够获得内存分配器认为的分配大小。这可能包括也可能不包括分配之前的任何标头(我猜可能不包括)。

    一种选择是分配几百万个小对象,然后查看您的程序使用了多少内存。然后再分配几百万,再看一遍。当操作系统为进程分配 RAM(或虚拟地址空间)时,总数通常会以块的形式增加,但是对于大量对象,这种“舍入错误”的影响通常会趋向于每个对象 0 字节。

    这应该告诉您您可能想知道的内容,即众多小堆对象的平均内存开销。它将包括内存分配器的任何记账开销,例如分配之前的标题,或用于跟踪分配和/或块的外部结构。

    【讨论】:

    • +1:进行测试的明智之举。您可以添加到此方法的另一件事是查看所有指针最终指向的位置,并查看您的实例在内存中的最终位置。
    【解决方案4】:

    如果您知道要进行大量小分配并且担心内存碎片,为什么不分配一个大缓冲区然后映射到其中呢?如果您进行大量的分配/解除分配,您可能还会看到一些性能改进。

    StackOverflow 有 some useful posts pertaining to avoiding memory fragmentation 可能会有一些用处。

    【讨论】:

      【解决方案5】:

      在 Windows 下,您可以使用 Heap32FirstHEAPENTRY32 结构来确定任何给定堆条目的大小,假设您没有使用自定义堆管理器。还值得指出的是,由于保护字节,分配块的大小在调试中可能比发布版本大。我在 MSDN 中没有看到提到 Heap64 函数,所以我猜他们只是使用 Heap32 名称。

      【讨论】:

        【解决方案6】:

        [编辑] 这个答案是错误的!我把它作为不做什么的例子。 sizeof function 运算符在编译时工作。


        你试过了吗:

        SomeClass* some_instance = new SomeClass;
        printf("Size of SomeClass == %u", sizeof(*some_instance) );
        

        我似乎记得通过传入一个类的实例,你应该得到分配的大小。

        【讨论】:

        • 这是 C++。 new 返回一个指针。 sizeof(SomeClass) 是问题中提到的“必要数量”,而不是“实际分配”的数量。
        • 你说的很对——我最近在做 C# 太多了!
        • 另外,sizeof 不是函数。在我之后重复一遍:sizeof 不是函数。它是一个一元(前缀)运算符,作用于实例(“对象”)或类型。在后一种情况下,参数看起来像是对该类型的强制转换,即 sizeof (char)。
        • 另一个好点。没有什么比不做的榜样更重要的了! :-/
        猜你喜欢
        • 1970-01-01
        • 2014-11-29
        • 1970-01-01
        • 1970-01-01
        • 2017-06-26
        • 1970-01-01
        • 2012-08-28
        • 1970-01-01
        相关资源
        最近更新 更多