私は物事を簡単にスキャンしました。
私のプロファイラーはすぐに、文法と (特に) lexer オブジェクトの構築にかなりのリソースを必要とすることを教えてくれました。
実際、SpiritParser.cpp の 1 行を変更するだけで、実行時間が 40%短縮されました1 (~28 秒から~17 秒):
lexer::Lexer lexer;
の中へ
static const lexer::Lexer lexer;
今、
とにかく、これらの追加の変更2 を実装すると、実行時間がさらに 15% 短縮されました。
static const lexer::Lexer lexer;
static const parser::EddiGrammar grammar(lexer);
try {
bool r = spirit::lex::tokenize_and_parse(
position_begin, position_end,
lexer,
grammar(boost::phoenix::cref(position_begin)),
program);
緩いアイデア:
- 静的レクサーの生成を検討しましたか (静的アナライザーの生成)
- バックトラッキングの量を潜在的に削減するために期待値を使用することを検討しましたか (注: 私はその分野では何も測定していません)
- と の代替案を検討しました
Position::file
かPosition::theLine
? 文字列のコピーは、必要以上に重いようです。保管したいconst char *
です。Boost Flyweightも参照してください。
qi::position
ディレクティブ内で事前スキップが本当に必要ですか?
- (あまり深刻ではありません: Spirit X3への移植を検討したことがありますか?移動のセマンティクスの形で潜在的な利点が約束されているようです。)
お役に立てれば。
[1]すべてのテスト ケースをtest/cases/*.eddi
100 回解析する場合(github) :
for (int i=0; i<100; i++)
for (auto& fname : argv)
{
eddic::ast::SourceFile program;
std::cout << fname << ": " << std::boolalpha << parser.parse(fname, program, nullptr) << "\n";
}
シンプルなタイミングで
time ./test ../../test/cases/*.eddi | md5sum
md5sum
健全性チェックとして機能します。
[2] https://github.com/wichtounet/eddic/pull/52の概念実証リファクタリングでプル リクエストを作成しました