如何测量std :: unordered_map的内存使用情况

时间:2014-08-19 03:17:17

标签: c++ unordered-map

我们知道基于哈希表的容器实现,如std::unordered_map use a lot memory,但我不知道多少是多少?

除了空间复杂性表示法,并且不考虑容器元素是否是指向更大对象的指针:

有没有办法弄清楚这样的容器在运行时使用了多少个字节

有没有办法在运行时告诉任何容器使用多少内存?

2 个答案:

答案 0 :(得分:15)

没有可移植的方式来判断正在使用多少字节。你能找到的是:

  • size()表示已将多少数据元素插入容器
  • bucket_count()表示基础哈希表有多少个桶,每个桶都可以预期将链接列表托管到关联的元素

现在:

    实际用于元素存储的
  • 字节为m.size() * sizeof(M::value_type)

  • 用于哈希表桶的
  • 字节取决于内部列表的存储方式 - std::unordered_map::bucket_size具有恒定的复杂性,因此我们可以合理地猜测它会是size()并且每个桶的头指针,所以m.bucket_count() * (sizeof(size_t) + sizeof(void*))是一个合理的猜测,尽管由于load_factor()有界而且没有{{}},因此可能只有摊销的复杂度。每桶存储{1}}(我更喜欢自己这样实现)

  • 如果每个插入的元素都是列表的一部分,则它们需要size指针,因此我们可以添加另一个next

  • 每个内存分配可以四舍五入到便于内存分配库管理的大小 - 例如下一个2的幂,接近100%最坏情况下的低效率和50%的平均值,所以让我们添加50%,仅用于列表节点,因为桶可能是两个给定m.size() * sizeof(void*)和指针的幂:50%* size_t

  • 特别是在调试模式下,可能会有任意数量的特定于实现的内务处理和错误检测数据

您可以通过创建许多大型表并查看size() * (sizeof(void*) + sizeof((M::value_type))或Process Manager如何报告不同的内存使用情况来进一步探索这一点。

答案 1 :(得分:6)

如果你想得到一个粗略的大小,我认为bucket_count()max_load_factor()就够了,它给出了当前的桶数和负载率。

理性:

  • 如果load_factor< = 1,则表示bucket_count()> =地图中的项目,则bucket_count()是内存使用量的大小。

    < / LI>
  • 如果load_factor&gt; 1,然后bucket_count() * load_factor表示地图中的最大项目。请注意,这是最大尺寸,而不是实际尺寸。

因此粗略的内存使用情况可能如下所示:

  unsigned n = mymap.bucket_count();
  float m = mymap.max_load_factor();
  if (m > 1.0) {
    return n * m;
  }
  else {
    return n;
  }

如果您想获得准确的内存使用量,您可能需要统计所有桶以查看其中有多少元素:

  size_t count = 0;
  for (unsigned i = 0; i < mymap.bucket_count(); ++i) {
    size_t bucket_size = mymap.bucket_size(i);
    if (bucket_size == 0) {
      count++;
    }
    else {
      count += bucket_size;
    }
  }