小N的std :: map vs unordered_map内存占用

时间:2015-08-22 20:10:02

标签: c++ c++11 gcc dictionary optimization

对于内存使用比速度更重要的嵌入式系统应用程序,最好使用的地图容器是什么? std::mapstd::unordered_map?这适用于N小于百分之一的情况。

如果实施很重要,那么我就关注libstdc ++实现(GCC)。

虽然我知道在内存使用方面无法击败简单数组,但我想避免使用具有O(N)性能的数据结构。因此,虽然我想减少内存占用,但我还希望查找速度合理(优于O(N))。我不关心其他操作(插入,移除),因为它们不经常发生。

如果我想进行自己的内存使用量测量,我将如何在Linux平台上进行此操作?

boost::flat_map是否适合作为一个关联容器,占用空间小,查找时间优于O(n)?

4 个答案:

答案 0 :(得分:3)

对于小N,有序矢量通常是最快的容器,并且具有最小的内存占用。 boost :: flat_map是一个实现,其他人称之为AssociativeVector。您可以使用std::lower_bound轻松实现它。由于必须对数据进行排序,因此插入和删除操作为O(n),因为数据必须在向量中移位。

使用排序向量,您可以执行二进制搜索,即O(log N)以进行检索。 std::lower_bound的复杂性是:

  

执行的比较次数在第一个和最后一个之间的距离是对数的(最多log2(最后一个)+ O(1)比较)

答案 1 :(得分:3)

作为替代my answer on vector,如果您事先知道密钥,也可以考虑哈希映射。您可以使用gperf生成完美的哈希函数,然后进行O(1)查找。实际速度取决于密钥类型。我已经看到std::map<string>的结果优于std::unordered_map<string>的情况,因为字符串的哈希函数必须处理完整的键字符串,而地图比较函数通常在前几个字符后停止。

如果速度很重要,请同时执行和基准测试。对于堆分析,我过去使用过google perftools

答案 2 :(得分:2)

如果不经常发生插入和删除,那么为什么不使用排序的std::mapstd::unordered_mapstd::vector进行查找,而不是std::lower_boundstd::equal_range。你获得ln(N)的查找速度和最小的空间。 boost::flat_map提供了一个很好的关联容器API,它以这种方式实现。一些详细的基准测试是herehere。另一种选择是开放地址哈希表。您必须进行一些实验,以确定这是否会满足您的内存限制,并且仍然比ln(N)提供更快的查找速度。两种解决方案都提供了良好的局部性,但是如果你想要零内存开销并且ln(N)对于查找来说足够快,那么我将使用已排序的数组。

答案 3 :(得分:2)

除了排序向量(如boost::flat_map)之外,您还可以查看google::dense_hash_map,它是一个哈希映射,存储与std::unordered_map相邻的数据,它分配节点分别。价格是需要专用的空键值和缺少迭代器失效保证。还有一个更紧凑的google::sparse_hash_map(虽然更慢)。