我似乎记得 cpp-netlib 使用 Spirit Qi 语法进行 URL 解析,例如
network/uri/accessors.hpp
network/uri/uri.ipp
在这种情况下,减速似乎是key_value_sequence
解析器accessors.hpp
这些模板非常繁重,编译需要相当长的时间,仅取决于所使用的编译器(根据我的经验,MSVC 最差)。
您可以阻止包含这些标头。至少只将它们包含在cpp
需要它的翻译单元中;永远不要让它陷入你的“常见”标题依赖项。这意味着编译器必须在每次迭代时重新编译这些东西(即使使用预编译的头文件,成本也可能很大)。
根据您的编译器版本,这些可能会有所帮助:
- 禁用调试信息 (-g0)
- 优化大小 (-Os)
- 定义 BOOST_SPIRIT_USE_PHOENIX_V3(从 ~1.58 开始默认)
- 定义
FUSION_MAX_VECTOR_SIZE
更小的数字(默认值:10)
真的,如果你使用支持 c++14 的 clang,我有兴趣测试一个补丁来使用 Spirit X3 而不是 Qi。
至少替换这个 Qi 解析器:
#include <boost/spirit/include/qi.hpp>
// ...
namespace details {
template <typename Map>
struct key_value_sequence : spirit::qi::grammar<uri::const_iterator, Map()> {
typedef typename Map::key_type key_type;
typedef typename Map::mapped_type mapped_type;
typedef std::pair<key_type, mapped_type> pair_type;
key_value_sequence() : key_value_sequence::base_type(query) {
query = pair >> *((spirit::qi::lit(';') | '&') >> pair);
pair = key >> -('=' >> value);
key =
spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("-+.~a-zA-Z_0-9/%");
value = +spirit::qi::char_("-+.~a-zA-Z_0-9/%");
}
spirit::qi::rule<uri::const_iterator, Map()> query;
spirit::qi::rule<uri::const_iterator, pair_type()> pair;
spirit::qi::rule<uri::const_iterator, key_type()> key;
spirit::qi::rule<uri::const_iterator, mapped_type()> value;
};
} // namespace details
template <class Map>
inline Map &query_map(const uri &uri_, Map &map) {
const uri::string_type range = uri_.query();
details::key_value_sequence<Map> parser;
spirit::qi::parse(boost::begin(range), boost::end(range), parser, map);
return map;
}
使用此 X3 变体:
#include <boost/spirit/home/x3.hpp>
// ...
namespace details {
namespace kvs_parser {
namespace x3 = boost::spirit::x3;
static auto const key = x3::char_("a-zA-Z_") >> *x3::char_("-+.~a-zA-Z_0-9/%");
static auto const value = +x3::char_("-+.~a-zA-Z_0-9/%");
template <typename Map, typename K = typename Map::key_type, typename V = typename Map::mapped_type, typename Pair = std::pair<K, V> >
static auto const pair = x3::rule<struct kvs_pair, Pair> {}
= key >> -('=' >> value);
template <typename Map>
static auto const query = pair<Map> >> *((x3::lit(';') | '&') >> pair<Map>);
}
} // namespace details
template <class Map>
inline Map &query_map(const uri &uri_, Map &map) {
const uri::string_type range = uri_.query();
spirit::x3::parse(boost::begin(range), boost::end(range), details::kvs_parser::query<Map>, map);
return map;
}
在我的系统上将编译时间从 ~8s 减少到 ~5s
BIG FAT WARNING X3 代码未经测试(我什至不知道它有什么用途,据我所知,我只是“盲目地”翻译成 X3)