【发布时间】:2015-10-27 05:55:20
【问题描述】:
当我在我的应用中进行一些性能测试时,我注意到以下代码 (Visual Studio 2010) 有所不同。
较慢的版本
while(heavyloop)
{
if(path+node+"/" == curNode)
{
do something
}
}
这将导致生成结果字符串的一些额外 malloc。
为了避免这些mallocs,我改成如下方式:
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设计得不是很好,由于历史原因。许多大型项目在用自定义字符串类替换字符串或检查字符串处理代码并重写以消除临时副本后发现了相当大的速度。 -
是的,我注意到了。在某些情况下,我将其替换为表现更好的 vector
(但代码当然没有那么好。:))。
标签: c++ optimization