ANTLR4 在 Python 中生成解析器速度较慢,但在 Java 中生成速度较快
Slow ANTLR4 generated Parser in Python, but fast in Java
我正在尝试转换 ant ANTLR3 grammar to an ANTLR4 grammar,以便在 antlr4-python2-runtime 中使用它。
这个语法是一个 C/C++ 模糊解析器。
转换后(基本上删除了树运算符和 semantic/syntactic 谓词),我使用以下方法生成了 Python2 文件:
java -jar antlr4.5-complete.jar -Dlanguage=Python2 CPPGrammar.g4
并且代码生成没有任何错误,所以我将其导入我的 python 项目(我正在使用 PyCharm)进行一些测试:
import sys, time
from antlr4 import *
from parser.CPPGrammarLexer import CPPGrammarLexer
from parser.CPPGrammarParser import CPPGrammarParser
currenttimemillis = lambda: int(round(time.time() * 1000))
def is_string(object):
return isinstance(object,str)
def parsecommandstringline(argv):
if(2!=len(argv)):
raise IndexError("Invalid args size.")
if(is_string(argv[1])):
return True
else:
raise TypeError("Argument must be str type.")
def doparsing(argv):
if parsecommandstringline(argv):
print("Arguments: OK - {0}".format(argv[1]))
input = FileStream(argv[1])
lexer = CPPGrammarLexer(input)
stream = CommonTokenStream(lexer)
parser = CPPGrammarParser(stream)
print("*** Parser: START ***")
start = currenttimemillis()
tree = parser.code()
print("*** Parser: END *** - {0} ms.".format(currenttimemillis()-start))
pass
def main(argv):
tree = doparsing(argv)
pass
if __name__ == '__main__':
main(sys.argv)
问题是解析很慢。一个包含 ~200 行的文件需要 5 分钟以上才能完成,而在 antlrworks 中解析同一文件只需要 1-2 秒。
分析 antlrworks 树,我注意到 expr
规则及其所有后代经常被调用,我认为我需要 simplify/change 这些规则来使解析器运行得更快:
我的假设是正确的还是我在转换语法时犯了一些错误?怎样才能使解析速度与 antlrworks 一样快?
更新:
我将相同的语法导出到 Java,只用了 795ms 就完成了解析。这个问题似乎更多地与 python 实现有关,而不是与语法本身有关。有什么可以加快 Python 解析的速度吗?
我读过 here python 比 java 慢 20-30 倍,但在我的情况下 python 慢了 ~400 倍!
我遇到了类似的问题,所以我决定用一个可能的解决方案来解决这个旧问题 post。我的语法 运行 立即使用 TestRig,但在 Python 上非常慢 3.
在我的例子中,错误是我用来生成单行注释的非贪婪标记(C/C++ 中的双斜杠,在我的例子中为 '%'):
TKCOMM : '%' ~[\r\n]* -> skip ;
这在某种程度上得到了来自 sharwell 的 post 的支持,在此讨论中:https://github.com/antlr/antlr4/issues/658
When performance is a concern, avoid using non-greedy operators, especially in parser rules.
要测试此场景,您可能需要从语法中删除非贪婪 rules/tokens。
我确认 Python 2 和 Python 3 运行时存在性能问题。通过几个补丁,我在 python3 运行时获得了 10 倍的加速(约 5 秒减少到约 400 毫秒)。
https://github.com/antlr/antlr4/pull/1010
张贴在这里,因为它可能对找到此主题的人有用。
自从这篇文章发布后,Antlr 的 Python 目标有了一些性能改进。也就是说,Python 解释器本质上会比 Java 或其他编译语言慢。
我已经为 Antlr 的 Python3 目标整合了一个 Python 加速器代码生成器。它使用 Antlr C++ 目标作为 Python 扩展。词法分析和解析完全在 C++ 中完成,然后使用自动生成的访问者在 Python 中重新构建生成的解析树。初步测试显示5x-25x 加速,具体取决于语法和输入,我对如何进一步改进它有一些想法。
这是代码生成工具:https://github.com/amykyta3/speedy-antlr-tool
这是一个功能齐全的示例:https://github.com/amykyta3/speedy-antlr-example
希望这对喜欢在 Python 中使用 Antlr 的人有用!
我最近在 python3 目标中使用 ANTLR。
一个 500~ 行的文件只需要不到 20 秒的时间来解析。
因此转向 Python3 目标可能会有所帮助
我正在尝试转换 ant ANTLR3 grammar to an ANTLR4 grammar,以便在 antlr4-python2-runtime 中使用它。 这个语法是一个 C/C++ 模糊解析器。
转换后(基本上删除了树运算符和 semantic/syntactic 谓词),我使用以下方法生成了 Python2 文件:
java -jar antlr4.5-complete.jar -Dlanguage=Python2 CPPGrammar.g4
并且代码生成没有任何错误,所以我将其导入我的 python 项目(我正在使用 PyCharm)进行一些测试:
import sys, time
from antlr4 import *
from parser.CPPGrammarLexer import CPPGrammarLexer
from parser.CPPGrammarParser import CPPGrammarParser
currenttimemillis = lambda: int(round(time.time() * 1000))
def is_string(object):
return isinstance(object,str)
def parsecommandstringline(argv):
if(2!=len(argv)):
raise IndexError("Invalid args size.")
if(is_string(argv[1])):
return True
else:
raise TypeError("Argument must be str type.")
def doparsing(argv):
if parsecommandstringline(argv):
print("Arguments: OK - {0}".format(argv[1]))
input = FileStream(argv[1])
lexer = CPPGrammarLexer(input)
stream = CommonTokenStream(lexer)
parser = CPPGrammarParser(stream)
print("*** Parser: START ***")
start = currenttimemillis()
tree = parser.code()
print("*** Parser: END *** - {0} ms.".format(currenttimemillis()-start))
pass
def main(argv):
tree = doparsing(argv)
pass
if __name__ == '__main__':
main(sys.argv)
问题是解析很慢。一个包含 ~200 行的文件需要 5 分钟以上才能完成,而在 antlrworks 中解析同一文件只需要 1-2 秒。
分析 antlrworks 树,我注意到 expr
规则及其所有后代经常被调用,我认为我需要 simplify/change 这些规则来使解析器运行得更快:
我的假设是正确的还是我在转换语法时犯了一些错误?怎样才能使解析速度与 antlrworks 一样快?
更新:
我将相同的语法导出到 Java,只用了 795ms 就完成了解析。这个问题似乎更多地与 python 实现有关,而不是与语法本身有关。有什么可以加快 Python 解析的速度吗?
我读过 here python 比 java 慢 20-30 倍,但在我的情况下 python 慢了 ~400 倍!
我遇到了类似的问题,所以我决定用一个可能的解决方案来解决这个旧问题 post。我的语法 运行 立即使用 TestRig,但在 Python 上非常慢 3.
在我的例子中,错误是我用来生成单行注释的非贪婪标记(C/C++ 中的双斜杠,在我的例子中为 '%'):
TKCOMM : '%' ~[\r\n]* -> skip ;
这在某种程度上得到了来自 sharwell 的 post 的支持,在此讨论中:https://github.com/antlr/antlr4/issues/658
When performance is a concern, avoid using non-greedy operators, especially in parser rules.
要测试此场景,您可能需要从语法中删除非贪婪 rules/tokens。
我确认 Python 2 和 Python 3 运行时存在性能问题。通过几个补丁,我在 python3 运行时获得了 10 倍的加速(约 5 秒减少到约 400 毫秒)。 https://github.com/antlr/antlr4/pull/1010
张贴在这里,因为它可能对找到此主题的人有用。
自从这篇文章发布后,Antlr 的 Python 目标有了一些性能改进。也就是说,Python 解释器本质上会比 Java 或其他编译语言慢。
我已经为 Antlr 的 Python3 目标整合了一个 Python 加速器代码生成器。它使用 Antlr C++ 目标作为 Python 扩展。词法分析和解析完全在 C++ 中完成,然后使用自动生成的访问者在 Python 中重新构建生成的解析树。初步测试显示5x-25x 加速,具体取决于语法和输入,我对如何进一步改进它有一些想法。
这是代码生成工具:https://github.com/amykyta3/speedy-antlr-tool
这是一个功能齐全的示例:https://github.com/amykyta3/speedy-antlr-example
希望这对喜欢在 Python 中使用 Antlr 的人有用!
我最近在 python3 目标中使用 ANTLR。 一个 500~ 行的文件只需要不到 20 秒的时间来解析。 因此转向 Python3 目标可能会有所帮助