我有一个应用程序,其中包含一个3运算符(& |!)布尔表达式求值程序,包含变量和常量。通常表达式不会太长(最多可能是50个术语,但通常要少得多)。可以有很多表达 - 我预计上限大约是一百万。目前我有一个手写的解析器,它有一个非常简单的求值器,它只是递归地遍历解析树。一个限制是必须从C ++中调用它。我没有表达式之间的共享。我想调查加快这一点。
我看到了两种研究途径。
此外,我希望代码生成方法比解析树或类似结构的解释方法更快。生成一些C ++代码可能相当简单,但考虑到函数的长度,我不知道像GCC这样的编译器是否能够优化CSE。
我已经看到有一些库可用于表达式评估,但在我的工作环境中添加第三方库并不简单,而且与我的需求相比,它们看起来都很复杂。
最后我最近一直在关注Antlr4,所以这对我来说可能是合适的。在过去,我一直致力于C代码生成,但我没有使用像LLVM这样的优化和代码生成的经验。
有关哪条路的建议?
答案 0 :(得分:1)
尽管我想建议ANTLR4,但我担心它不能满足您的性能需求。它的自适应LL(*)算法有很多内容,尽管有一些常见的技巧可以提高它的性能,但只需在运行时跟踪ANTLR4解释器就可以看出,除非你当前的表达式求值器效率很低,否则很可能比ANTLR4更快,这是一种工业级引擎,旨在支持比你的语法复杂得多的语法。当LALR(1)DFA shift-reduce引擎不支持我的语法时,我使用ANTLR,并以ANTLR4的额外解析能力来获得性能提升。
答案 1 :(得分:0)
据我所知,你的问题更多的是关于更快的表达评估,而不是更快的表达解析。所以我的答案将集中在前者身上。毕竟,解析不应该成为瓶颈,因为你的表达式语言看起来很简单,可以为它实现一个手动调整的解析器。
因此,为了加速您的评估,您可以考虑使用LLVM JIT执行您的公式。也就是说,根据您的公式F
,您可以(相对)轻松生成相应的LLVM IR并直接评估它。这SMT solver就是这么做的。 IR代码生成在单个C ++类here中实现。
请注意,您提到的布尔表达式是该解算器支持的SMT语言的子集。此外,您可以轻松调整LLVM优化器需要的积极程度。
然而,IR生成和优化有其开销。因此,如果给定公式的评估不足以分摊初始开销,那么我建议直接解释。在这种情况下,您可以查找找到结构相似性和常见子表达式的机会。