我正在使用ANTLRv4生成的解析器来处理具有多个核心的计算机上的大量文件。为了获得额外的速度,我想并行处理文件。
要检查解析器性能是否受CPU限制,我将文件拆分成组并使用独立进程对其进行解析,每个进程在专用JVM实例中运行相同的解析器。这大大提高了性能。
这鼓励我尝试使用多个线程而不是进程,但是没有成功。我创建了两个工作线程,每个线程都有自己的解析器,词法分析器和文件流实例。返回的结果是正确的,但是,使用两个线程实际上需要比使用一个线程稍长的时间。
为了确保我正确使用线程并且JVM安装没有问题,我暂时用代码来替换解析代码,代码计算Fibonacci序列:在这种情况下,使用多个线程会导致性能提升
分析这种行为,我发现当使用多个解析线程时,没有一个CPU达到高使用率。看起来线程正在争夺一些共享资源。
看一下ANTLR源代码,我在ParserATNSimulator.java中找到了以下注释:
“同一个解析器的所有实例通过静态字段共享相同的决策DFA。每个实例都有自己的ATN模拟器,但它们共享相同的decisionToDFA字段。它们还共享一个PredictionContextCache对象,确保共享所有PredictionContext对象在DFA州中。这会产生很大的差异。“
我想知道对这些共享资源的同步访问是否会导致性能问题。如果是这样,是否有可能创建这些资源的唯一实例?或者甚至可能有一个更简单的问题解决方案?
提前致谢!
费边
答案 0 :(得分:5)
使用多个解析器线程时,ANTLR 4运行时的参考版本设计为安全(只要使用多个解析器实例)。我维护了一个ANTLR 4的备用(非官方)分支,它以不同的方式实现核心算法,以提高多线程场景的性能。
这个分支在某些领域暴露了一个稍微不同的API,因此它不是安装版本4的ANTLR 4的直接替代品。