我已经编写了一个小测试,我试图比较调整容器大小的运行速度,然后使用std::generate_n
填充它。我正在比较std::string
和std::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
?
答案 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秒。对于较长的字符串,结果应该不同。
当然,除了两件事之外,这并没有真正证明什么: