可能重复:
Boost Spirit QI slow
我目前正在尝试使用Boost Spirit QI进行CSV数据解析。
我正在使用1GB CSV文件运行测试。每行看起来像
123|123|\n
并且文件大约有60Mio。行。
我后来想为任意CSV文件生成解析器,我知道列的数据类型。所以我首先使用语法将行解析为整数行(由两个整数组成的结构的向量):
csv = *(int_ >> lit('|') >> int_ >> lit('|'));
在大约2秒钟内解析文件并填充向量。对于我的基准测试,我首先将CSV文件加载到内存中的std :: string(因此从磁盘加载文件不会影响性能)。
现在我尝试了相同但是使用语法将第一列解释为字符串列(使用std :: string和int解析为包含std :: string和int的结构的向量):
csv = *(lexeme[*~char_('|')] >> lit('|') >> int_ >> lit('|'));
现在解析需要12秒,内存消耗也在飙升。我确保我没有交换(swapoff) - 所以这不是瓶颈。我想知道为什么在Spirit QI中解析分隔的字符串是如此低效。我的意思是应该比解析后的字符串memcpy
更昂贵。还有更好的方法吗?
更新:分隔字符串显然似乎是性能瓶颈。将行解释为double和int以及语法csv = *(double_ >> lit('|') >> int_ >> lit('|'));
也会在2秒内解析文件。
更新2(代码):
namespace test
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct row
{
std::string a;
int b;
};
}
BOOST_FUSION_ADAPT_STRUCT(
test::row,
(std::string, a)
(int, b)
)
namespace test
{
template <typename Iterator>
struct row_parser : qi::grammar<Iterator, std::vector<row>(), ascii::space_type>
{
row_parser() : row_parser::base_type(start)
{
using qi::int_;
using qi::lit;
using qi::double_;
using qi::lexeme;
using ascii::char_;
start = *(lexeme[*~char_('|')] >> lit('|') >> int_ >> lit('|'));
}
qi::rule<Iterator, std::vector<row>(), ascii::space_type> start;
};
}
using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef test::row_parser<iterator_type> row_parser;
std::vector<test::row> v;
row_parser g;
std::string str;
string dataString(buffer, fileSize); // buffer contains the CSV file contents, fileSize is its size
auto startBoostParseTime = chrono::high_resolution_clock::now();
string::const_iterator iter = dataString.begin();
string::const_iterator end = dataString.end();
phrase_parse(iter, end, g, space, v);
auto endBoostParseTime = chrono::high_resolution_clock::now();
auto boostParseTime = endBoostParseTime - startBoosParseTime ;
cout << "Boost Parsing time: " << boostParseTime.count()<< " result size "<< v.size() <<endl;