这个函数从一个字符串中读取一个双精度数组:
vector<double> parseVals(string& str) {
stringstream ss(str);
vector<double> vals;
double val;
while (ss >> val) vals.push_back(val);
return vals;
}
当使用包含 100 万个数字的字符串调用时,该函数需要 7.8 秒才能执行(Core i5,3.3GHz)。这意味着解析一个数字需要花费 25000 个 CPU 周期。
user315052 指出,相同的代码在他的系统上运行速度要快一个数量级,进一步的测试表明不同系统和编译器之间的性能差异非常大(另见 user315052 的回答):
1. Win7, Visual Studio 2012RC or Intel C++ 2013 beta: 7.8 sec
2. Win7, mingw / g++ 4.5.2 : 4 sec
3. Win7, Visual Studio 2010 : 0.94 sec
4. Ubuntu 12.04, g++ 4.7 : 0.65 sec
我在 Boost/Spirit 库中找到了一个很好的替代方案。代码安全、简洁且速度极快(在 VC2012 上为 0.06 秒,比 stringstream 快 130 倍)。
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
vector<double> parseVals4(string& str) {
vector<double> vals;
qi::phrase_parse(str.begin(), str.end(),
*qi::double_ >> qi::eoi, ascii::space, vals);
return vals;
}
虽然这从实际角度解决了问题,但我仍然想知道为什么 stringstream 的性能如此不一致。我分析了程序以识别瓶颈,但 STL 代码对我来说看起来像乱码。任何熟悉 STL 内部的人的评论将不胜感激。
PS:在上述所有时间中,优化都是 O2 或更好。程序配置文件中既不是字符串流的实例化,也不是矢量图的重新分配。几乎所有的时间都花在提取操作符内部。