【发布时间】:2010-10-31 06:27:40
【问题描述】:
我有一个程序使用太多内存在堆上分配大量小对象。所以我想研究优化它的方法。该程序使用 Visual C++ 7 编译。
有没有办法确定给定对象实际分配了多少内存?我的意思是当我调用 new 时,堆会分配 不少于 必要的数量。我怎样才能知道到底分配了多少?
【问题讨论】:
-
你在什么平台上运行?
标签: c++ visual-c++ memory memory-management
我有一个程序使用太多内存在堆上分配大量小对象。所以我想研究优化它的方法。该程序使用 Visual C++ 7 编译。
有没有办法确定给定对象实际分配了多少内存?我的意思是当我调用 new 时,堆会分配 不少于 必要的数量。我怎样才能知道到底分配了多少?
【问题讨论】:
标签: c++ visual-c++ memory memory-management
没有确切的答案,因为一些堆管理器可能会使用不同数量的内存来进行相同大小的顺序分配。此外,(通常)没有直接的方法来测量特定分配占用的字节数。
您可以通过分配一定数量的相同大小的项目(例如,4096)并注意所用内存的差异来近似此值。将后者除以前者会给你答案。请注意,此值会随着操作系统、操作系统版本和操作系统版本的不同而变化,有时应用程序的调试版本可能会启用额外的堆跟踪,这会增加开销。在某些操作系统上,用户可以更改堆策略(即默认使用一个堆分配器与另一个堆分配器)。示例:Windows 和 pageheap.exe
仅供参考,Windows 32 位上的默认(不是 LFH)堆占用:
【讨论】:
您可能正在寻求迁移到内存池模型(这是先前关于“分配大型池”的答案所描述的内容。由于内存池不需要每次分配的开销,它们可以节省大量空间小对象。如果一组小对象的生命周期很短(即你分配了一堆小对象然后需要摆脱很多),内存池也快得多,因为你可以直接释放池每个对象。
维基百科有一些关于该技术的信息以及一些实现的链接:
http://en.wikipedia.org/wiki/Memory_pool
您应该能够通过简单的网络搜索找到其他实现。
【讨论】:
不一定以独立于平台的方式。我不记得任何手头的细节(除了我很确定你没有使用的操作系统),但你的操作系统可能会提供一种测试 malloc 分配的“大小”的方法,新的可能使用 malloc 或等效项。因此,您可能能够获得内存分配器认为的分配大小。这可能包括也可能不包括分配之前的任何标头(我猜可能不包括)。
一种选择是分配几百万个小对象,然后查看您的程序使用了多少内存。然后再分配几百万,再看一遍。当操作系统为进程分配 RAM(或虚拟地址空间)时,总数通常会以块的形式增加,但是对于大量对象,这种“舍入错误”的影响通常会趋向于每个对象 0 字节。
这应该告诉您您可能想知道的内容,即众多小堆对象的平均内存开销。它将包括内存分配器的任何记账开销,例如分配之前的标题,或用于跟踪分配和/或块的外部结构。
【讨论】:
如果您知道要进行大量小分配并且担心内存碎片,为什么不分配一个大缓冲区然后映射到其中呢?如果您进行大量的分配/解除分配,您可能还会看到一些性能改进。
StackOverflow 有 some useful posts pertaining to avoiding memory fragmentation 可能会有一些用处。
【讨论】:
在 Windows 下,您可以使用 Heap32First 和 HEAPENTRY32 结构来确定任何给定堆条目的大小,假设您没有使用自定义堆管理器。还值得指出的是,由于保护字节,分配块的大小在调试中可能比发布版本大。我在 MSDN 中没有看到提到 Heap64 函数,所以我猜他们只是使用 Heap32 名称。
【讨论】:
你试过了吗:
SomeClass* some_instance = new SomeClass;
printf("Size of SomeClass == %u", sizeof(*some_instance) );
我似乎记得通过传入一个类的实例,你应该得到分配的大小。
【讨论】: