我们知道基于哈希表的容器实现,如std::unordered_map
use a lot memory,但我不知道多少是多少?
除了空间复杂性表示法,并且不考虑容器元素是否是指向更大对象的指针:
有没有办法弄清楚这样的容器在运行时使用了多少个字节?
有没有办法在运行时告诉任何容器使用多少内存?
答案 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()是内存使用量的大小。
如果load_factor
> 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;
}
}