"resurrect"(序列化/和反序列化)标准的最快方法::map
Fastest way to "resurrect" (serialize/ and deserialize) an std::map
作为测试代码的一部分,我需要构建复杂的结构,其中使用2个std::map实例;它们都有大约100万个元素。在优化的构建中,这是可以的,然而,在调试未优化的构建时,这几乎需要一分钟的时间。我使用相同的数据来构建地图,基本上,如果我能保存大块ram并在20ms内恢复它,那么我就可以在我的应用程序中有效地获得相同的地图,而无需每次等待一分钟。我能做些什么来加快速度?我可以尝试使用自定义分配器并保存/恢复其满负荷存储,或者有没有一种方法可以从已经排序的数据中构造std::map,这样它在时间上就会是线性的?
技术难点在于,对于调试模式下的std::map,Visual studio编译器会插入正确性检查,在某些修订版中,还会在结构中插入元素以确保检查更容易。
有两种可能的解决方案:-
抽象
如果std::map
提供的信息可以由接口类替换,那么std::map的内部可以被隐藏并移动到一个单独的编译单元中。这可以在调试环境之外进行编译,并恢复性能。
替代数据结构
对于一条基本上是静态的信息(例如,一条需要快速检索的静态数据),std::map
不是实现这一点的最快方法,而std::pair<key,value>
的排序std::vector
在操作中会更具性能
std::vector
的优点是它的布局有保证。如果数据是Plain旧数据,那么它可以由std::vector::reserve
和memcpy加载。否则,在std::vector
中填充元素仍然可以避免Visual Studio为问题跟踪std::map
的内存和结构所花费的大量时间。
在尝试了不同的方法后,我最终使用了自定义分配器。
std::map
是我的结构用来保存数据的许多容器之一。分配的ram的总大小实际上约为400MB,该结构包含不同数据的列表、映射和向量,其中这些容器的许多成员是指向其他容器的指针。所以,我采取了激进的方法,用所有的映射和内部指针快速"复活"我的整个结构。虽然最初在我的帖子中,它是关于在修改代码并增加额外复杂性后,使其在调试构建中"快速",但它也同样适用于发布构建:在发布构建中,构建时间约为10秒。
所以,一开始我修改了所有结构成员以使用我的自定义分配器,这样我就可以看到实际分配了多少ram:
total allocated: 1970339320 bytes, total freed: 1437565512 bytes
这样,我可以估计我总共需要大约600MB。然后,在我的自定义分配器中,我添加了静态全局方法my_aloc::start_recording(。调用start_recording后,我会复制我的整个结构(它实际上是一个结构向量)。在进行复制时,不会出现过度分配,每个结构成员只为其存储分配了足够的内存。基本上,通过复制结构,它实际上只分配了大约400MB,而不是600MB。我说过,在我的构造中,有很多指向内部成员的指针,如何重用我的自定义分配器中录制的400MB的"快照"?我可以编写代码来"修补"指针,但也许它甚至不起作用:我有很多映射也使用指针作为键,自定义比较结构可以取消引用指针,将实际指针与值进行比较。此外,有些映射在列表中包含迭代器,处理这些会非常混乱。此外,我的整体结构并不是一成不变的,它正在进行中,如果有什么变化,那么补丁代码也需要改变。因此,答案是显而易见的:我只需要在同一个基本地址加载整个400MB的快照。在windows中,我使用VirtualAlloc,在linux中,可能需要使用mmap之类的东西,或者可以使用boost共享mem-lib来使其更具可移植性。最后,总加载时间降到了150毫秒,而在发布版中,我需要10秒以上的时间,而在调试构建中,它可能已经在几分钟内了。
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- 创建可以遍历 std::map 值的通用模板迭代器的最简单方法是什么?
- 返回 std::map with get 方法
- 从基于迭代器的for循环转换后,如何在map::find()中调用方法
- 方法中填充的shared_ptr到map在调用者中返回为空
- 从std::map值中获取密钥的有效方法
- 为什么 memcpy() 是一种将元素添加到 'std::map' 的方法?
- std::map 索引运算符与插入方法的性能
- 当对象为值时访问实例方法<map>
- 最有效的安全方法将 std::map<int, std::shared_ptr> 转换为 std::<Base>map<int, std::shared_ptr<D
- 在std :: Map或std :: set中找到具有给定前缀的键的优雅方法
- STD :: MAP-使用下标操作员与插入方法添加元素
- 使用类方法插入STD :: MAP
- boost-python 当C++方法返回 std::map<string,X*>
- 有没有一种直接、快速的方法可以将列表"map"到<VectorXd> MatrixXd?
- 访问std::map中元素的最有效方法是什么
- 添加和初始化新std::map元素的最有效方法是什么
- 如何使用 Ruby 的 Enumerable .map 方法在 C++ 中执行类似于 map 的操作
- "resurrect"(序列化/和反序列化)标准的最快方法::map
- 迭代 std::map 的更好方法