为什么ANTLR4解析器会累积ATNConfig对象?

时间:2015-01-19 02:27:49

标签: antlr4

在使用ANTLR开发Parser for C ++时,我们进行了批量解析测试用例,其中构造了一个新的解析器来解析每个C ++源文件。开始时性能可以接受 - 每个文件大约15秒。但在解析了大约150多个文件后,每个文件的解析时间越来越长,最后jvm会超出" GC限制超过"错误。

使用JProfiler,我们发现解析每个文件后会逐渐累积许多ATNConfig对象。从大约70M开始,它们稳定地堆积到500M以上,直到堆接近满,GC占用100%的CPU时间。 JProfiler识别的最大对象(保留堆中最多对象的对象)包括DFA []和PredictionContextCache。

需要注意的一点是,我们使用了2个线程来同时运行解析任务。虽然线程不共享任何解析器或解析树对象,但我们注意到ANTLR生成的解析器正在使用静态字段,这可能导致多线程设置中的内存问题。无论如何,这只是一个嫌疑人。

有没有人知道" ATNConfig积累的原因是什么?#34;?有解决方案吗?

1 个答案:

答案 0 :(得分:1)

ATNConfig实例在运行时用于动态DFA构造。所需的实例数是语法和输入的函数。有几种解决方案可供选择:

  1. 增加您为应用程序提供的内存量。尝试-Xmx12g作为起点,看看问题是否是应用程序的内存太少。
  2. 每个ATNConfig都属于DFA个实例,代表特定决策的DFA。如果您知道包含最多ATNConfig个实例的决策,您可以在语法中简化这些决策。
  3. 通过调用Recognizer.clearDFA()定期清除缓存的DFA。请注意,过于频繁地清除DFA会损害性能(如果可能,请不要完全清除DFA)。
  4. 您可以使用ANTLR 4的“优化”分支。该项目的分支旨在减少内存占用,这可以极大地帮助复杂语法的性能,但代价是某些简单语法的速度。