矢量插入与push_back性能问题
vector insert vs push_back performance issue
当我分析我的程序时,我发现了一个瓶颈:
for (int i = 0; i < len; ++i) {
vec->push_back(buffer[i]);
}
for循环位于一个称为100k次的函数中。用以下代码替换它后,性能提升是巨大的。(上面的代码占用了总时间的 10%。下面的代码需要 0.34%(
vec->insert(vec->end(), buffer, buffer + len);
所讨论的向量具有以下类型:vector<char>* vec
谁能解释一下为什么第二个版本要快得多?
我也尝试在第一个版本中保留空间,但没有明显的改进。
如果没有大量的数据,就很难明确地说出为什么一段重要的代码比另一段执行得更快,尤其是当涉及第三方代码(在这种情况下是内部vector
代码(时。但你通常可以做一些猜测。
既然你说提前reserve
没有区别,我的猜测是它只是归结为所需的操作数量。在你的原始代码中,作为第一近似值,总是会有len
索引操作到buffer
,len
调用push_back
*,以及运行循环的一些开销。但是,对insert
的调用不一定如此。该函数的朴素实现可能只是遍历迭代器,并为每个值调用push_back
,在这种情况下,您希望看到大致相同的性能。但是,更精明的实现可能会意识到该操作归结为复制单个连续的 len
字节运行,并利用机器指令,这些指令可以有效地将其作为单个操作实现(如果初始缓冲区大小太小,则可能之前会调整大小/复制(。但确定的唯一方法是查看所涉及的实际标准库和/或机器代码。
没有提到你正在使用什么编译器,但只是为了它,我在VS2012中实现了类似于你的代码的东西并跟踪了它。 insert
最终确实利用了一次调用来执行复制memmove
。
*这是一个近似值,因为如果push_back
作为内联函数实现,并且您的编译器设置允许它被内联,则优化器可能会在该循环中度过一个现场日。当我说如果没有大量具体数据,关于性能的推理可能会很棘手时,我得到了这种事情。
Vector 使用数组作为其底层存储。所以,它会自动在到达阵列末尾之前将其数组大小扩展 2 倍同时使用push_back等方法。
但是在插入的情况下,vector 将为插入准备足够的存储空间,因为 vector 知道将插入多少个元素。这意味着只发生 1 次扩展。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 大小相等但成员数量不同的结构之间的性能差异
- 为什么constexpr的性能比正常表达式差
- 在类中使用随机生成器时出现性能问题
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 海湾合作委员会 ARM 性能下降
- 推导 std::vector::back() 的返回类型
- GCC 和 Clang 代码性能的巨大差异
- 在容量内调整矢量大小时的性能影响
- 了解算法的性能差异(如果以不同的编程语言实现)
- 未达到的情况会影响开关外壳性能
- QStringList vs list<shared_ptr<QString>> 性能比较C++
- 是否总是可以将使用递归编写的程序重写为不使用递归的程序C++,性能观点是什么?
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 哪种方法更好,性能明智
- C++ 特征库:引用的性能开销<>
- 与多个 for 循环与单个 for 循环 wrt 相关的性能从多映射获取数据
- 基于范围的 for 循环range_declaration中各种说明符之间的性能差异