“恢复”(序列化/反序列化)std :: map的最快方法

时间:2016-06-03 20:57:41

标签: c++ stdmap

作为我的测试代码的一部分,我需要构建复杂的结构,使用其他东西2 std :: map实例;它们都有大约100万个元素。在优化的构建中,没关系,但是,在调试未优化的构建中,它需要将近一分钟。我使用相同的数据来构建该地图,基本上如果我可以保存一大块ram并在20ms内恢复它,那么我会在我的应用程序中有效地获取相同的地图,而不必每次都等待一分钟。我该怎么做才能加快速度?我可以尝试使用自定义分配器并保存/恢复其同步存储,或者有没有办法从已经排序的数据构造std :: map,以便它在时间上是线性的?

2 个答案:

答案 0 :(得分:1)

技术难点是,对于调试模式下的std :: map,Visual Studio编译器会插入检查的正确性,并且在某些修订中,已将元素插入到结构中以确保检查更容易。

有两种可能的解决方案: -

抽象

如果std::map提供的信息可由接口类替换,则可以隐藏std :: map的内部并将其移动到单独的编译单元中。这可以在调试环境之外编译并恢复性能。

替代数据结构

对于一条广泛静态的信息(例如,您需要快速检索的静态数据),std::map不是实现此目的的最快方式,而std::vector的{​​{1}} {1}}在操作中会更有效率。

std::pair<key,value>的优点是它的布局有保证。如果数据是普通旧数据,则可以通过std::vector和memcpy加载。否则,填充std::vector::reserve中的元素仍然可以避免Visual Studio跟踪std::vector的内存和结构所花费的大量时间。

答案 1 :(得分:0)

最终尝试不同的方法后,我最终使用了custom allocator

std::map是我的结构用于保存数据的众多容器之一。分配的ram的总大小实际上大约是400MB,结构包含列表,映射,不同数据的向量,其中这些容器的许多成员是指向其他容器的指针。所以,我采取了激进的方法,并且非常快速地复活了#39;我的整个结构包含所有地图和内部指针。虽然最初在我的帖子中它是关于使它快速&#39;在修改代码并增加额外的复杂性之后,在调试中快速构建它同样适用于发布版本:在发布版本中,构建时间变为大约10秒。

所以,首先我修改了所有结构成员以使用我的自定义分配器,这样我就看到了实际分配了多少ram:

total allocated: 1970339320 bytes, total freed: 1437565512 bytes

这样我估计我总共需要600MB左右。然后,在我的自定义分配器中,我添加了静态全局方法my_aloc :: start_recording()此方法将分配600MB的ram块,并且在调用start_recording之后,我的自定义分配器将只返回该600MB块的地址。在调用start_recording之后,我会复制我的整个结构(它实际上是一个结构向量)。在制作副本时没有过度分配,每个结构成员只为其存储分配了足够的ram。基本上通过复制结构,它实际上只分配了大约400MB而不是600MB。 我说在我的构造内部有很多指向内部成员的指针,如何重用然后这个400MB记录&#34;快照&#34;从我的自定义分配器?我可以把代码编写到&#34; patch&#34;指针,但也许它甚至不起作用:我有很多地图也使用指针作为自定义比较结构的键,取消引用指针来比较实际指针与值。此外,一些映射包含迭代器到列表中,处理所有这些将是非常混乱的。此外,我的整体结构并不是一成不变的,它正在进行中,如果有什么变化,那么修补代码也需要改变。所以,答案显而易见:我只需要在同一个基址上加载整个400MB的快照。在windows中我使用VirtualAlloc,在Linux中可能需要使用类似mmap的东西,或者可以使用boost shared mem lib来使其更具可移植性。最后整体加载时间下降到150毫秒,而在发布时我需要10秒以上,而在调试版本中,它现在可能只需几分钟就可以了。