我偶然发现了std::string
的糟糕表现。我预计来自某些外部数据(例如std::string
)的新std::string(X.c_str())
创建将大致相当于data = malloc(X.size())
+ strcpy(data, X.c_str())
,并且会有一些小的常量开销。
一些示例性能代码:
#include <string>
#include <string.h>
#include <assert.h>
static const char SampleString[] =
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
"Hello world. Hello world. Hello world. Hello world. Hello world. "
;
static size_t N = 1000000;
// mostly for avoiding compiler optimization
void readStr(const char* _s) {
volatile const char* s = _s;
while(*s) ++s;
}
void cppStringLoop1() {
for(size_t i = 0; i < N; ++i) {
std::string tmp(SampleString);
readStr(&tmp[0]);
}
}
void cppStringLoop2() {
for(size_t i = 0; i < N; ++i) {
std::string tmp(SampleString, SampleString + sizeof(SampleString));
readStr(&tmp[0]);
}
}
void cStringLoop() {
for(size_t i = 0; i < N; ++i) {
char* tmp = (char*) malloc(sizeof(SampleString));
memcpy(tmp, SampleString, sizeof(SampleString));
readStr(tmp);
free(tmp);
}
}
int main(int argc, char** argv) {
assert(argc >= 2);
if(strcmp(argv[1], "-c") == 0) cStringLoop();
else if(strcmp(argv[1], "-c++1") == 0) cppStringLoop1();
else if(strcmp(argv[1], "-c++2") == 0) cppStringLoop2();
else assert(false);
return 0;
}
似乎MSVC处于发布模式,我的初步假设是正确的。 (发布模式= MSVC发布运行时lib +优化。)
但是,在调试模式下(MSVC Debug Runtime lib +没有优化),看起来这个假设是错误的。开销不是很小(约为175%)。
也许它也是MSVC 2012 std::string
实施。这里有一些数字:
$ time ./TestStringPerf.exe -c
real 0m6.879s
user 0m0.015s
sys 0m0.015s
$ time ./TestStringPerf.exe -c++1
real 0m10.524s
user 0m0.000s
sys 0m0.000s
$ time ./TestStringPerf.exe -c++2
real 0m10.106s
user 0m0.000s
sys 0m0.015s
或许这只是期望的开销。
答案 0 :(得分:8)
您继续使用sizeof(SampleString)
。 SampleString
是一个指针。因此,您的C代码和cppStringLoop2
函数仅复制大约4-8个字符。
您需要:
sizeof(SampleString)
的使用更改为std::strlen(SampleString)
; static const char* SampleString
更改为static const char SampleString[]
并在某些地方使用sizeof(SampleString)
,在其他地方使用sizeof(SampleString) - 1
(即cppStringLoop2
功能)。