cpp-netlib が URL 解析に Spirit Qi グラマートを使用していることを覚えているようです。
network/uri/accessors.hpp
network/uri/uri.ipp
この場合、スローダウンはkey_value_sequence
パーサーのようですaccessors.hpp
これらは非常にテンプレートが多く、コンパイルにかなりの時間がかかりますが、使用するコンパイラにわずかに依存します (私の経験では、MSVC が最悪です)。
これらのヘッダーが含まれないようにすることができます。少なくとも、cpp
それを必要とする翻訳単位 ( s) にのみ含めてください。「一般的な」ヘッダーの依存関係に巻き込まれないようにしてください。これは、コンパイラが各反復でそのようなものを再コンパイルする必要があることを意味します (プリコンパイル済みヘッダーを使用しても、コストはかなりのものになる可能性があります)。
コンパイラのバージョンによっては、次のことが役立ちます。
- デバッグ情報を無効にする (-g0)
- サイズの最適化 (-Os)
- BOOST_SPIRIT_USE_PHOENIX_V3 を定義します (~1.58 以降のデフォルト)
- より小さな数値のようなものを定義
FUSION_MAX_VECTOR_SIZE
します (デフォルト: 10)
実際、c++14 対応の clang を使用している場合は、Qi の代わりに Spirit X3 を使用するパッチをテストすることに興味があります。
少なくともこの 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;
}
私のシステムでは、コンパイル時間が最大 8 秒から最大 5 秒に短縮されます
BIG FAT WARNING X3 コードはテストされていません (何がそれを使用しているのかさえわかりません。私の知る限り、「やみくもに」X3 に変換しただけです)。