当我在我的应用程序中进行性能测试时,我注意到以下代码(Visual Studio 2010)有所不同。
较慢的版本
这将导致生成结果字符串时需要额外的malloc操作。
为了避免这些malloc操作,我进行了以下更改:
虽然第二个版本与第一个版本相比看起来有点尴尬,但它仍然足够可读。我想知道的是,这种优化是编译器疏忽导致的,还是必须手动完成。由于它只改变了分配的顺序,我希望编译器也可以自己解决。另一方面,某些条件必须满足才能真正实现优化,这些条件可能没有得到满足,但如果条件不满足,代码至少会像第一个版本一样执行。新版本的Visual Studio在这方面是否更好?
下面是一个SSCE演示区别:
较慢的版本
while(heavyloop)
{
if(path+node+"/" == curNode)
{
do something
}
}
这将导致生成结果字符串时需要额外的malloc操作。
为了避免这些malloc操作,我进行了以下更改:
std::string buffer;
buffer.reserve(500); // Big enough to hold all combinations without the need of malloc
while(heavyloop)
{
buffer = path;
buffer += node;
buffer += "/";
if(buffer == curNode)
{
do something
}
}
虽然第二个版本与第一个版本相比看起来有点尴尬,但它仍然足够可读。我想知道的是,这种优化是编译器疏忽导致的,还是必须手动完成。由于它只改变了分配的顺序,我希望编译器也可以自己解决。另一方面,某些条件必须满足才能真正实现优化,这些条件可能没有得到满足,但如果条件不满足,代码至少会像第一个版本一样执行。新版本的Visual Studio在这方面是否更好?
下面是一个SSCE演示区别:
std::string gen_random(std::string &oString, const int len)
{
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
oString = "";
for (int i = 0; i < len; ++i)
{
oString += alphanum[rand() % (sizeof(alphanum) - 1)];
}
return oString;
}
int main(int argc, char *argv[])
{
clock_t start = clock();
std::string s = "/";
size_t adds = 0;
size_t subs = 0;
size_t max_len = 0;
s.reserve(100000);
for(size_t i = 0; i < 1000000; i++)
{
std::string t1;
std::string t2;
if(rand() % 2)
{
// Slow version
//s += gen_random(t1, (rand() % 15)+3) + "/" + gen_random(t2, (rand() % 15)+3);
// Fast version
s += gen_random(t1, (rand() % 15)+3);
s += "/";
s += gen_random(t2, (rand() % 15)+3);
adds++;
}
else
{
subs++;
size_t pos = s.find_last_of("/", s.length()-1);
if(pos != std::string::npos)
s.resize(pos);
if(s.length() == 0)
s = "/";
}
if(max_len < s.length())
max_len = s.length();
}
std::cout << "Elapsed: " << clock() - start << std::endl;
std::cout << "Added: " << adds << std::endl;
std::cout << "Subtracted: " << subs << std::endl;
std::cout << "Max: " << max_len << std::endl;
return 0;
}
在我的系统上,这两者之间大约有1秒的差异(这次使用gcc进行测试,但在Visual Studio中似乎没有任何显着的差异):
Elapsed: 2669
Added: 500339
Subtracted: 499661
Max: 47197
Elapsed: 3417
Added: 500339
Subtracted: 499661
Max: 47367
std::string
由于历史原因设计得不太好。许多大型项目在使用自定义字符串类替换其字符串或检查其字符串处理代码并重写以消除临时副本后,发现速度显著提升。 - M.M