std::map 中的内存分配

Posted

技术标签:

【中文标题】std::map 中的内存分配【英文标题】:Memory Allocation in std::map 【发布时间】:2009-02-08 15:57:28 【问题描述】:

我正在对各种 C++ 字典实现(地图、字典、向量等)进行报告。

使用 std::map 插入的结果表明性能为 O(log n)。性能也有持续的峰值。我不是 100% 确定是什么原因造成的;我认为它们是由内存分配引起的,但我未能找到任何文献/文档来证明这一点。

任何人都可以解决这个问题或指出正确的方向吗?

干杯。

【问题讨论】:

我认为行为在很大程度上取决于实现(因为 STL 没有指定应该如何实现,只指定如何使用)。 @restevens -- 这不对,STL 应该如何表现有一个定义(即每种容器的 big-O 性能应该是什么)。 @rstevens:这是错误的。 STL 容器是根据对不同操作复杂性的保证来定义的。 【参考方案1】:

你是对的:它是 O(log n) 复杂度。但这是由于 map 的排序特性(通常基于二叉树)。

另请参阅http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html 插入注释。如果您可以提示在哪里进行插入,最坏的情况是 O(log n) 和摊销 O(1)。

地图通常基于二叉树,需要平衡以保持良好的性能。您观察到的负载峰值可能与此平衡过程相对应

【讨论】:

我最初认为尖峰是由树的旋转引起的,但直到 50,000 个项目被插入到地图中才出现尖峰。在此数字之后,每 25,000 个项目(大约)一致地出现峰值,每个项目的幅度一致。 我回答晚了,但它可能有用:可以在每次插入时执行平衡,操作量最少,所以我猜测的尖峰是当量时执行的重新分配已达到为元素预分配的内存。【参考方案2】:

对于 STL,经验方法并非绝对必要。当标准明确规定诸如 std::map 插入之类的操作的最小复杂性时,进行试验是没有意义的。

我敦促您阅读该标准,以便在继续实验之前了解最低复杂性保证。当然,您碰巧测试的任何 STL 实现都可能存在错误。但是流行的 STL 是经过良好调试的生物并且使用非常广泛,所以我对此表示怀疑。

【讨论】:

【参考方案3】:

如果我没记错的话,std::map 是一个平衡的红黑树。当 std::map 确定底层树需要平衡时,可能会导致一些尖峰。此外,当分配新节点时,操作系统可能会在分配部分造成一些峰值。

【讨论】:

std::map 的 GCC 实现实际上是一棵红黑树。我相信 MS VS 也使用红黑树,但我不能 100% 确定这一点。尖峰很可能是树的重新平衡。

以上是关于std::map 中的内存分配的主要内容,如果未能解决你的问题,请参考以下文章

std::unordered_map 析构函数不释放内存?

在 C++ std::unordered_map 中预分配桶

Linux 内核 内存管理内存管理架构 ③ ( Linux 内核中的内存管理模块 | 页分配器 | 不连续页分配器 | 内存控制组 | 硬件设备内存管理 | MMU | 页表缓存 | 高速缓存 )

Linux 内核 内存管理内存管理架构 ③ ( Linux 内核中的内存管理模块 | 页分配器 | 不连续页分配器 | 内存控制组 | 硬件设备内存管理 | MMU | 页表缓存 | 高速缓存 )

C语言中的动态内存分配的用法举例

在 C++ 中的 2D 动态内存分配数组中释放分配的内存