这是个好主意吗?出于某种原因,我认为它应该比boost的tokenizer或split更快。但是大部分时间我都陷入了boost :: spirit :: compile
template <typename Iterator>
struct ValueList : bsq::grammar<Iterator, std::vector<std::string>()>
{
ValueList(const std::string& sep, bool isCaseSensitive) : ValueList::base_type(query)
{
if(isCaseSensitive)
{
query = value >> *(sep >> value);
value = *(bsq::char_ - sep);
}
else
{
auto separator = bsq::no_case[sep];
query = value >> *(separator >> value);
value = *(bsq::char_ - separator);
}
}
bsq::rule<Iterator, std::vector<std::string>()> query;
bsq::rule<Iterator, std::string()> value;
};
inline bool Split(std::vector<std::string>& result, const std::string& buffer, const std::string& separator,
bool isCaseSensitive)
{
result.clear();
ValueList<std::string::const_iterator> parser(separator, isCaseSensitive);
auto itBeg = buffer.begin();
auto itEnd = buffer.end();
if(!(bsq::parse(itBeg, itEnd, parser, result) && (itBeg == itEnd)))
result.push_back(buffer);
return true;
}
我已按照上面的说明实现了它。我的代码出了什么问题?或者只是因为在运行时定义了分隔符,重新编译是不可避免的?
EDIT001:
示例并与使用CoLiRu上的tokenizer的boost :: split和original imp的可能实现进行比较
看起来coliru现在已经失败了。在任何情况下,这些都是对字符串“2lkhj309 | ioperwkl | 20sdf39i | rjjdsf | klsdjf230o | kx23904iep2 | xp39f4p2 | xlmq2i3219”的1M运行结果,带分隔符“|”
8000000在1081ms内分裂。
8000000分裂在1169ms。
8000000 在2663ms分裂。
首先是tokenizer,第二个是boost :: split,第三个是boost :: spirit
答案 0 :(得分:4)
首先,不同的版本不会做同样的事情:
input.getText()
修复了它,但它似乎不是boost::split
的功能)是的,使用动态分隔符重新编译是不可避免的。但不,这不是瓶颈(其他方法也有动态分隔符):
我做了一些优化。时间安排:
boost::tokenizer
8000000 original (boost::tokenizer) rate: 2.84257μs
10000000 possible (boost::split) rate: 3.09941μs
10000000 spirit (dynamic version) rate: 1.45456μs
10000000 spirit (direct version, avoid type erasure) rate: 1.25588μs
next step:
10000000 spirit (precompiled sep) rate: 1.18059μs
本地系统g ++:
8000000 original (boost::tokenizer) rate: 2.92805μs
10000000 possible (boost::split) rate: 2.75442μs
10000000 spirit (dynamic version) rate: 1.32821μs
10000000 spirit (direct version, avoid type erasure) rate: 1.10712μs
next step:
10000000 spirit (precompiled sep) rate: 1.0791μs
正如你所看到的,灵魂方法不需要慢。我采取了哪些步骤? http://paste.ubuntu.com/11001344/
sehe@desktop:/tmp$ time ./test
8000000 original (boost::tokenizer) rate: 1.80061μs
10000000 possible (boost::split) rate: 1.29754μs
10000000 spirit (dynamic version) rate: 0.607789μs
10000000 spirit (direct version, avoid type erasure) rate: 0.488087μs
next step:
10000000 spirit (precompiled sep) rate: 0.498769μs
)2.742μs。 no_case[char_(delimiter)]
子规则(由于类型擦除的非终端规则,减少了复制和动态调度)2.579μs。 制作分隔符字符集而不是字符串文字:2.693μs。
请参阅coliru上的intermediate version。 (我推荐下面的代码,它更清理了)
使用qi :: raw []代替std :: string合成属性(避免复制!)0.624072μs
value
实施)速率:0.491011μs 现在看来很明显,每次都不会“编译”分隔符,所有实现都会受益。我没有为所有的方法做到这一点,但为了好玩,让我们为Spirit版本做:
<强> Live On Coliru 强>
spirit_direct