例如,我有一个已知sizeof(A)和sizeof(B)的std :: map,而map里面有N个条目.你会如何估计它的内存使用量?我会说它就像是
(sizeof(A) + sizeof(B)) * N * factor
但是因素是什么?可能不同的公式?
也许要求上限更容易?
估计数将更接近
(sizeof(A) + sizeof(B) + ELEMENT_OVERHEAD) * N + CONTAINER_OVERHEAD
您添加的每个元素都有开销,并且还有一个固定的开销用于维护用于存储映射的数据结构的数据结构.这通常是二叉树,例如红黑树.例如,在GCC中,C++ STL实现ELEMENT_OVERHEAD
将是sizeof(_Rb_tree_node_base)
并且CONTAINER_OVERHEAD
将会是sizeof(_Rb_tree)
.对于上图,您还应该添加用于存储地图元素的内存管理结构的开销.
通过测量各种大型集合的代码内存消耗来估算可能更容易.
你可以使用Curtis Bartley的MemTrack.它是一个内存分配器,它取代了默认的内存分配器,可以跟踪内存使用情况,直至分配类型.
输出的一个例子:
----------------------- Memory Usage Statistics ----------------------- allocated type blocks bytes -------------- ------ ----- struct FHRDocPath::IndexedRec 11031 13.7% 2756600 45.8% class FHRDocPath 10734 13.3% 772848 12.8% class FHRDocElemPropLst 13132 16.3% 420224 7.0% struct FHRDocVDict::IndexedRec 3595 4.5% 370336 6.2% struct FHRDocMDict::IndexedRec 13368 16.6% 208200 3.5% class FHRDocObject * 36 0.0% 172836 2.9% struct FHRDocData::IndexedRec 890 1.1% 159880 2.7% struct FHRDocLineTable::IndexedRec 408 0.5% 152824 2.5% struct FHRDocMList::IndexedRec 2656 3.3% 119168 2.0% class FHRDocMList 1964 2.4% 62848 1.0% class FHRDocVMpObj 2096 2.6% 58688 1.0% class FHRDocProcessColor 1259 1.6% 50360 0.8% struct FHRDocTextBlok::IndexedRec 680 0.8% 48756 0.8% class FHRDocUString 1800 2.2% 43200 0.7% class FHRDocGroup 684 0.8% 41040 0.7% class FHRDocObject * (__cdecl*)(void) 36 0.0% 39928 0.7% class FHRDocXform 516 0.6% 35088 0.6% class FHRDocTextColumn 403 0.5% 33852 0.6% class FHRDocTString 407 0.5% 29304 0.5% struct FHRDocUString::IndexedRec 1800 2.2% 27904 0.5%
如果您真的想知道运行时内存占用,请使用自定义分配器并在创建映射时将其传递给它.请参阅Josuttis的书和他的这个页面(用于自定义分配器).
也许要求上限更容易?
上限取决于确切的实现(例如,使用的平衡树的特定变体).也许,您可以告诉我们您为什么需要这些信息,以便我们能够提供更好的帮助
我最近需要自己回答这个问题,并简单地使用在MSVC 2012下以64位模式编译的std :: map编写了一个小的基准程序.
一个拥有1.5亿个节点的地图已经浸透了大约15GB,这意味着8字节L,8字节R,8字节int键和8字节数据,总共32个字节,吸收了大约2/3rds的内存节点的地图内存,留下1/3的叶子.
就个人而言,我发现这个内存效率出乎意料地差,但它就是它的本质.
希望这是一个方便的经验法则.
PS:std :: map的开销是单个节点大小AFAICT的开销.