繁体   English   中英

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

[英]Why is std::vector<char> faster than std::string?

我写了一个小测试,试图比较调整容器大小的运行速度,然后使用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何在?

我使用#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

std :: vector每次都会领先。 由于它似乎更高效,因此使用std :: string的意义何在?

即使我们假设您的观察结果适用于各种不同的系统和不同的应用程序上下文,出于各种原因使用std::string还是有道理的,所有这些原因都基于一个事实,即字符串的语义与一个向量。 字符串是一段文本(至少是简单的,非国际化的英文文本),向量是字符的集合。

我想到两件事:

  • 使用方便。 std::string可以从字符串文字构造而成,具有许多方便的运算符,并且可以使用特定于字符串的算法。 尝试std::string x = "foo" + ("bar" + boost::algorithm::replace_all_copy(f(), "abc", "ABC").substr(0, 10) with 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
}

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

当然,除了两点以外,这实际上也没有证明任何东西:

  • 性能测试在很大程度上取决于环境。
  • 性能测试应测试将在实际程序中实际执行的操作。 对于字符串,您的程序可能会处理许多小字符串,而不是一个巨大的字符串,因此请测试小字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM