计算无序映射占用的内存空间
Calculating memory space occupied by unordered maps
我有两个无序映射:(代码在linux中执行)
第一个无序映射:
至少包含65536个条目。每个条目由
组成int
unsigned char
unsigned char
第二个无序映射:
小于65536个条目。每个条目由
组成int
int
int
vector <char>
现在我想根据上面两个无序映射所占用的内存(以字节为单位)对两者进行比较。之后我想计算内存压缩实现。请指导我如何找到这两张无序地图占用的内存?
第二个无序映射的更多细节:
typedef std::tuple<int, int> key_t;
struct KeyHasher
{
std::size_t operator()(const key_t& k) const
{
using boost::hash_value;
using boost::hash_combine;
// Start with a hash value of 0 .
std::size_t seed = 0;
// Modify 'seed' by XORing and bit-shifting in
// one member of 'Key' after the other:
hash_combine(seed,hash_value(std::get<0>(k)));
hash_combine(seed,hash_value(std::get<1>(k)));
// Return the result.
return seed;
}
};
struct Ndata
{
int value;
vector<char> accept ;
};
typedef boost::unordered_map<const key_t,Ndata,KeyHasher> SecondMap;
}
如果不查看STL使用的精确unordered_map
实现,我不认为可以精确地回答您的问题。
然而,基于unordered_map
接口,您可以做出适当的有根据的猜测:
一个unordered_map
需要存储:
-
一个
bucket
容器(可能是一个矢量结构) -
max_bucket_count
bucket(可能是单链表结构) -
每个条目都有一个完整的条目(不仅是值,还有键,以处理键哈希冲突)
在快速查看libc++实现之后,您还需要存储空间:
-
哈希函数对象
-
相等性测试函数对象
-
分配器函数对象
考虑到这一点,我的估计是这样的:
typedef unordered_map<K, V, ...> tMyMap;
size_t getMemoryUsage(const tMyMap& map) {
auto entrySize = sizeof(K) + sizeof(V) + sizeof(void*);
auto bucketSize = sizeof(void*);
auto adminSize = 3 * sizeof(void*) + sizeof(size_t);
auto totalSize = adminSize + map.size() * entrySize + map.max_bucket_count() * bucketSize();
return totalSize;
}
这只适用于第一种情况,因为在第二种情况下,根据每个向量的大小,每个条目的内存使用可能完全不同。对于第二种情况,您必须添加如下内容:
size_t getMemoryUsage(const tMyMap& map) {
auto entrySize = sizeof(K) + sizeof(V) + sizeof(void*);
auto bucketSize = sizeof(void*);
auto adminSize = 3 * sizeof(void*) + sizeof(size_t);
auto totalSize = adminSize + map.size() * entrySize + map.max_bucket_count() * bucketSize();
auto contentSize = 0;
for (const auto& kv : map) {
// since accept is a vector<char>,
// it uses capacity() bytes of additional memory
contentSize += kv.second.accept.capacity();
}
totalSize += contentSize;
return totalSize;
}
然而,考虑到现实世界的分配逻辑,您的map实际使用的内存可能与此有很大不同,例如由于外部碎片。如果您想100%确定unordered_map使用了多少内存,您还需要考虑分配器的行为。
一种可能的方法是通过使用自定义分配器进行实验来找到答案。
一个直接的解决方案可以利用c++ 11的"Scoped allocator model"(参见The Scoped allocator model (Rev 2), Stroustrup: Scoped allocator)。"作用域分配器"将应用于容器,并将递归地应用于容器的元素。
为std::unordered_map
及其元素提供这样一个自定义分配器将使您能够精确地计算块的数量、大小和总量。
顺便说一下,作用域分配器还可以让您优化内存消耗和性能,例如通过提供"竞技场分配器"。
这里有一个警告:尽管C+11一致性需要作用域分配器模型,但很可能它没有在编译器供应商提供的标准库中实现。例如,clang的标准库为所有容器完全实现了作用域分配器。关于GCC,请阅读这里:GCC状态,以及GCC邮件列表。
编辑:一个完全不同的方法是使用工具来分析内存消耗。例如,Xcode IDE提供了一个优秀的工具"Instruments",它提供了各种分析方法,其中一个用于跟踪堆和对象分配。比较两个不同的版本只需要几秒钟。当然,可用的工具因您的平台而异;)
我建议创建一个包含您的地图的数组。您将能够创建大量内存(例如1万个),然后可以将总内存(由操作系统显示)除以1万个。当然,您需要考虑开销(分配映射之前的内存消耗)(包括数组)。
执行大量sizeof操作是没有帮助的,因为对于堆上的每个分配,您都有一个实现定义的开销。例如,在Visual Studio 2013中,在Release中分配是通过8个字节的倍数完成的(或者对于大数组是16个字节)。
- 当注入程序的内存空间时,如何读取从 0 到 0xFFFFFFFFF 的每个字节?我正在创建模式扫描仪
- 为什么不同的翻译单元没有独立和沙盒的内存空间?
- 我的boost managed_shared_memory在离开作用域时似乎不会从内存空间中取消映射
- 是否可以在专用内存空间中分配一个为提升管理共享内存而创建的对象
- 为什么我只能在 4 GB 的虚拟内存空间上分配 2 GB?
- OPENCL-如何使辅助功能返回阵列并将内存的部分从恒定内存空间转移到私有
- 为多维数组创建内存空间
- 将节点添加到链接列表中,而无需明确分配内存空间(无需使用新)
- 内存空间的反转方向?
- 打开文件*以增加内存空间
- 为什么堆栈中的函数局部变量之间存在内存空间
- 只有当声明一个对象时,内存空间才会分配给类的数据成员,那么为什么 Sizeof(class_name) 给我结果
- 何时分配C++类的成员函数的内存空间
- 使用free()释放new分配的内存空间
- 共享内存空间可以将数据(非POD)发送到另一个共享内存吗?
- 删除内存空间后,指针的值保持不变还是更改?对象内容是否将被更改
- 如何在分配更多内存空间之前检查指针是否为 NULL
- 需要析构函数来释放内存空间,即使所有项目都已弹出
- 数组的指针,该数组的每个元素的内存空间信息存储在哪里
- C++内存空间