我在代码库中混合使用CString
,const char*
和std::string
(非unicode),其中所有新代码都使用std::string
。我现在必须做以下事情:
{
CString tempstring;
load_cstring_legacy_method(tempstring);
stdstring = tempstring;
}
并担心性能。这些字符串是DNA序列,因此我们可以很容易地拥有100多个字符串~3M字符。请注意,调整load_cstring_legacy_method
不是一种选择。我做了一个快速测试:
// 3M
const int stringsize = 3000000;
const int repeat = 1000;
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
for ( int i = 0; i < repeat; ++i ){
CString cstring('A', stringsize);
std::string stdstring(cstring); // Comment out
cstring.Empty();
}
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime).count() << " ms" << std::endl;
并评论std::string
给出850 ms
,其分配为3600 ms
。差异的程度令人惊讶,所以我猜基准测试可能没有达到我的预期。假设有一个惩罚,有没有办法可以避免它?
答案 0 :(得分:1)
所以你的问题是让std :: string构造更快?
在我的机器上,比较这个
std::string stdstring(cstring); // 4741 ms
我以这种方式获得更好的表现:
std::string stdstring(cstring, stringsize); // 3419 ms
或者如果std :: string已经存在,就像问题的第一部分所示:
stdstring.assign(cstring, stringsize); // 3408 ms
答案 1 :(得分:0)
使用更有效的内存分配器。像记忆竞技场/区域这样的东西会大大有助于分配成本。
如果你真的非常绝望,理论上你可以将ReleaseBuffer与一些可怕的分配器黑客结合起来以完全避免副本。但这会带来很多痛苦。
此外,如果您遇到严重问题,可以考虑更改字符串实现。 Visual Studio附带的std::string
使用SSO或小字符串优化。这听起来确实如此 - 它优化了非常小的字符串,这种字符串很常见,但不一定适合这种用例。像COW这样的另一个实现可能更合适(如果在多线程环境中这样做,请非常小心)。
最后,如果您使用的是旧版本的VS,则还应考虑升级。就性能而言,移动语义是一个巨大的应变。
答案 2 :(得分:0)
CString
可能是Unicode版本,这解释了缓慢。通用转换例程无法知道所使用的字符仅限于“ACGT”。
然而,你可以无耻地利用这一点。
{
CString tempstring;
load_cstring_legacy_method(tempstring);
int len = tempstring.GetLength();
stdstring.reserve(len);
for(int i = 0; i != len; ++i)
{
stdstring.push_back(static_cast<char>(tempstring[i]));
}
}
便携式?只有CString
,所以Windows变种。