为什么std :: vector <char>比std :: string更快?</char>

时间:2014-08-30 10:03:46

标签: c++ string c++11 vector stl

我已经编写了一个小测试,我试图比较调整容器大小的运行速度,然后使用std::generate_n填充它。我正在比较std::stringstd::vector<char>。这是程序:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>

int main()
{
    std::random_device rd;
    std::default_random_engine rde(rd());
    std::uniform_int_distribution<int> uid(0, 25);

    #define N 100000

#ifdef STRING
    std::cout << "String.\n";
    std::string s;
    s.resize(N);
    std::generate_n(s.begin(), N, 
                    [&]() { return (char)(uid(rde) + 65); });
#endif

#ifdef VECTOR
    std::cout << "Vector.\n";
    std::vector<char> v;
    v.resize(N);
    std::generate_n(v.begin(), N, 
                    [&]() { return (char)(uid(rde) + 65); });
#endif

    return 0;
}

我的Makefile

test_string:
    g++ -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test test.cpp -DSTRING
    valgrind --tool=callgrind --log-file="test_output" ./test
    cat test_output | grep "refs"

test_vector:
    g++ -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test test.cpp -DVECTOR
    valgrind --tool=callgrind --log-file="test_output" ./test
    cat test_output | grep "refs"

N的某些值的比较:

N=10000
String: 1,865,367
Vector: 1,860,906

N=100000
String: 5,295,213
Vector: 5,290,757

N=1000000
String: 39,593,564
Vector: 39,589,108

std::vector<char>每次都会提前出现。由于它似乎更具性能,甚至使用std::string

的重点是什么

2 个答案:

答案 0 :(得分:5)

我使用了#define N 100000000。每个场景测试3次,在所有场景中字符串更快。不使用Valgrind,它没有意义。

OS: Ubuntu 14.04. Arch:x86_64 CPU: Intel(R) Core(TM) i5-4670 CPU @ 3.40GHz.

$COMPILER -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test x.cc -DVECTOR    
$COMPILER -std=c++11 -O3 -Wall -Wextra -pedantic -pthread -o test x.cc -DSTRING

时间:

compiler/variant           | time(1) | time(2) | time(3)
---------------------------+---------+---------+--------
g++ 4.8.2/vector    Times: | 1.724s  | 1.704s  | 1.669s
g++ 4.8.2/string    Times: | 1.675s  | 1.678s  | 1.674s
clang++ 3.5/vector  Times: | 1.929s  | 1.934s  | 1.905s
clang++ 3.5/string  Times: | 1.616s  | 1.612s  | 1.619s

答案 1 :(得分:3)

  

std :: vector每次都会提前出现。因为它似乎更多   高性能,使用std :: string甚至是什么意思?

即使我们假设您的观察结果适用于各种不同的系统和不同的应用程序上下文,因此出于各种原因使用std::string仍然有意义根源于字符串具有与向量不同的语义。字符串是一段文本(至少是简单的非国际化英文文本),矢量是一组字符。

我想到了两件事:

  • 易于使用。 std::string可以用字符串文字构造,有很多方便的操作符,可以使用特定于字符串的算法。尝试使用std::string x = "foo" + ("bar" + boost::algorithm::replace_all_copy(f(), "abc", "ABC").substr(0, 10) ...

  • std::vector<char>
  • std::string在MSVC中使用小字符串优化(SSO)实现,在许多情况下完全消除了堆分配。 SSO是基于观察到字符串通常非常短,当然不能说关于向量。

尝试以下方法:

#include <iostream>
#include <vector>
#include <string>

int main()
{
    char const array[] = "short string";

#ifdef STRING
    std::cout << "String.\n";
    for (int i = 0; i < 10000000; ++i) {
        std::string s = array;
    }
#endif

#ifdef VECTOR
    std::cout << "Vector.\n";
    for (int i = 0; i < 10000000; ++i) {
        std::vector<char> v(std::begin(array), std::end(array));
    }
#endif
}

std::string版本应该优于std::vector版本,至少与MSVC相同。在我的机器上差异大约2-3秒。对于较长的字符串,结果应该不同。

当然,除了两件事之外,这并没有真正证明什么:

  • 性能测试在很大程度上取决于环境。
  • 性能测试应该测试在真实程序中实际完成的内容。对于字符串,您的程序可能会处理许多小字符串而不是单个字符串,因此请测试小字符串。