我最近注意到我程序中的 std::move for std::string 在某种程度上比直接复制赋值要慢。
例如,
#include <string>
#include <vector>
#include <chrono>
#include <iostream>
int main(int argc, char *argv[])
{
size_t len(atoi(argv[1]));
std::string str, tmp;
std::vector<std::string> v(1000000);
for (auto& i : v)
{
i.reserve(len);
for (size_t j(0); j < len; j++)
i.push_back('0' + (j % 10));
}
str.reserve(len);
std::chrono::duration<double, std::milli> d;
auto c(std::chrono::steady_clock::now());
for (size_t i(0); i < v.size(); i++)
{
//str = v[i]; // copy assignment
str = std::move(v[i]); // move
}
d = std::chrono::steady_clock::now() - c;
std::cout << d.count() << "ms\n";
}
我通过以下方式编译它:g++-8 -std=c++17 -o test test.cpp
下面是一些测试结果:
short string(10bytes) * 1000000
-O0:
copy: ~60ms
move: ~100ms
-O3:
copy: ~8.4ms
move: ~7.5ms
short string(100bytes) * 1000000
-O0:
copy: ~64ms
move: ~110ms
-O3:
copy: ~9.4ms
move: ~15ms
long string(1000bytes) * 1000000
-O0:
copy: ~190ms
move: ~107ms
-O3:
copy: ~107ms
move: ~16ms
有些地方让我很困惑。
为什么不做优化,10bytes的字符串和100bytes的字符串速度一样?
为什么大多数时候复制比没有优化的移动更快?
为什么 O3 在复制 1000 字节的字符串时速度较慢?
********** 6/23 更新 **********
抱歉回复晚了。感谢所有的回放和评论。
我用一个大小等于“v”的 vector 来替换“str”,最后把它的所有元素写入一个文件。
经过这次改动,结果更加合理,可以解决我的第一个和第二个问题。
small-string-optimization 在 10bytes string 的情况下使复制比 move 更快,而我的原始程序中其他情况的结果受到复制省略的影响。
下面是更合理的结果
short string(10bytes) * 1000000
-O0:
copy: ~66ms
move: ~98ms
-O3:
copy: ~9ms
move: ~9ms
short string(100bytes) * 1000000
-O0:
copy: ~185ms
move: ~99ms
-O3:
copy: ~73ms
move: ~7ms
long string(1000bytes) * 1000000
-O0:
copy: ~570ms
move: ~100ms
-O3:
copy: ~510ms
move: ~7ms
但在这个结果中,我的第三个问题仍然存在。
我记得编译器会使用 simd 来改进 O2 或更高优化的复制,但在 100 字节和 1000 字节的情况下,复制的速度似乎并不显着。
最佳答案
只是猜测,但是当您移动一个字符串时,实际上是在删除另一个字符串的内容。在复制案例中不会发生这种情况。为什么不将所有字符串变量和操作移到一个单独的函数中并在该函数之外测量时间?您可能会得到不同的结果。
关于c++ - std::move 对于不同长度的 std::string 的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56707165/