内存高效的std :: map替代方案

时间:2016-12-20 11:34:56

标签: c++ database memory stdmap

我正在使用std::map来存储大约2000万个条目。如果它们在没有任何容器开销的情况下存储,则需要大约650MB的内存。但是,由于它们是使用std::map存储的,因此占用大约15GB的内存(即太多)。

我使用std::map的原因是因为我需要找到等于/大于/小于x的密钥。这就是sparsehash这样的东西不起作用的原因(因为,使用它,我无法通过比较找到键)。

是否可以使用std::map(或一般的有序地图)来减少内存使用量?

编辑:写作性能很多比阅读性能更重要。它可能只读取约10个条目,但我不知道它将读取哪些条目。

4 个答案:

答案 0 :(得分:4)

你是在动态写作还是在查找完成之前写一次?如果情况稍晚,则您不需要地图,可以使用std::vector和一次性排序。

你可以将未排序的所有东西都插入到向量中,在所有东西都存在后排序一次(O(N * log N)以及std::map,但更好的性能特征)然后在排序中查找数组(O(logN)为std::map)。

特别是如果您在阅读之前知道元素的数量并且可以预先保留矢量大小,那么可以很好地工作。或者至少如果你知道一些"上限"保留可能比实际需要的更多,但避免重新分配。

答案 1 :(得分:3)

另一种方法是使用Boost.Containers中的flat_map:它支持与std::map相同的接口,但由排序的连续数组(想象std::vector)支持一棵树或者根据相同的想法手动推出自己的解决方案。

由于后端不同,其性能特征当然不同。由你来评估它是否适用于你的情况。

答案 2 :(得分:3)

根据您的要求:

  1. 插入需要快速
  2. 要阅读的内容很多
  3. 回读可能很慢
  4. 您只回读一次数据
  5. 我会考虑typedef std::pair<uint64, thirty_six_byte_struct> element;并填充std::list<element>。这在性能方面很难被击败。

    对于回读,我只是遍历链表,在每个点检查是否需要其中一个元素。这是一个O(N)遍历,但正如你所说,你只会这样做一次。

答案 3 :(得分:3)

原来问题不是 std::map

我意识到使用3个独立的地图来表示相同数据的各个部分,在将其减少到1之后,内存的差异完全可以忽略不计。

再看一下代码,我意识到我编写的代码是为了释放一个非常昂贵的结构(地图的每个元素)实际上没有用。

修复该部分,它现在使用&lt; 1GB内存,应该! :)

TL; DR: std::map的开销完全可以忽略不计。问题是我自己的。