小字符串优化(SSO)和移动语义

时间:2015-06-03 10:47:05

标签: c++ performance c++11

std::string test = "small_string";

std::string test2_1 = test;   // line 1

std::string test2_2 = std::move(test); // line 2

嗨,我很好奇哪个版本的字符串创建速度很快。 test2_1test2_2

我正在研究std::string的VC ++版本上的工具,发现test2_1版本会调用memcpy(_First1, _First2, _Count))test2_2会调用memmove(_First1, _First2, _Count)),并且我只是想知道哪一个更好,如果我希望我的代码运行得更快。

=============================================== ===============

嗨,我只是做一些测试,有些东西我无法理解......这是我的测试代码:

{
    Timer t;
    for (int i = 0; i < 1000000; i++){
        char s[] = "small_string";
        char t[10];

        memcpy(&t, &s, 10);
        //std::cout << t << std::endl;
    }

    std::cout << "test, memcpy: " << t.elapsed() << " second" << std::endl;
}


{
    Timer t;
    for (int i = 0; i < 1000000; i++){
        char s[] = "small_string";
        char t[10];
        memmove(&t, &s, 10);
       // std::cout << t << std::endl;
    }

    std::cout << "test, memmove: " << t.elapsed() << " second" << std::endl;
}


{
    Timer t;
    for (int i = 0; i < 1000000; i++){

        std::string test = "small_string";
        std::string test2_1 = test;   // line 1
    }

    std::cout << "test, str copy: " << t.elapsed() << " second" << std::endl;
}


{
    Timer t;
    for (int i = 0; i < 1000000; i++){

        std::string test = "small_string";
        std::string test2_2 = std::move(test); // line 2
    }
    std::cout << "test, str move: " << t.elapsed() << " second" << std::endl;
}

,结果是:(调试版本)

测试,memcpy:0.0090005秒

测试,memmove:0.0110006秒

test,str copy:4.92528 second

测试,str move:4.52926秒

我知道memcpy应该比memmove更快,而我的前两个测试用例证明了这一点。但是std :: string的结果是不同的...移动版本比复制版本快。我不知道为什么即使查看std :: string的实现,我也找不到任何可以说服我这样做的事情。

=============================================== ======

结果:(发布版本)

测试,memcpy:0秒

测试,memmove:0.0080004秒

test,str copy:0.0330019 second

测试,str move:0.0290017秒

1 个答案:

答案 0 :(得分:1)

  

嗨,我很好奇哪个版本的字符串创建速度很快。 test2_1或test2_2?

这似乎是过早优化的一个明显例子。这两种形式甚至都不相同,所以问哪种形式更快是荒谬的。

编写做正确事情的代码,只有在出现性能问题时才会担心愚蠢的微优化。

第1行使test保持不变,因此保持相同的值。第2行修改test,使其处于未指定状态。

如果您的代码在创建其他字符串后不依赖于test的值,那么您应该使用std::move,因为它表达了所需的语义(如果字符串不适合肯定更快的小字符串缓冲区。

如果您的代码之后关注test的值,请不要使用std::move,只需复制一份。

对苹果和橘子之间的差异进行基准测试是浪费时间。

对调试版本中的微小差异进行基准测试是一个巨大的浪费时间。如果您关心性能,则需要启用优化。