2

我正在使用 ANTLRv4 生成的解析器来处理具有多核机器上的大量文件。为了获得一些额外的速度,我想并行处理文件。

为了检查解析器性能是否受 CPU 限制,我将文件分成组,并使用独立进程解析它们,每个进程在专用 JVM 实例中运行相同的解析器。这大大提高了性能。

这鼓励我尝试使用多个线程而不是进程进行相同的尝试,但是没有成功。我创建了两个工作线程,每个线程都有自己的解析器、词法分析器和文件流实例。返回的结果是正确的,但是,使用两个线程实际上比使用一个线程花费的时间稍长。

为了确保我正确使用线程并且 JVM 安装没有问题,我暂时将解析代码替换为计算斐波那契序列的代码:在这种情况下,使用多个线程会提高性能。

分析这种行为,我发现当使用多个解析线程时,没有一个 CPU 达到高使用率。看起来线程正在争夺一些共享资源。

看了一下ANTLR源代码,在ParserATNSimulator.java中发现如下注释:

“同一个解析器的所有实例通过一个静态字段共享相同的决策 DFA。每个实例都有自己的 ATN 模拟器,但它们共享相同的 decisionToDFA 字段。它们还共享一个 PredictionContextCache 对象,确保所有 PredictionContext 对象在 DFA 之间共享状态。这有很大的不同。

我想知道对这些共享资源的同步访问是否会导致性能问题。如果是这样,是否有可能创建这些资源的唯一实例?或者是否有更简单的解决方案?

提前致谢!

费边

4

1 回答 1

5

ANTLR 4 运行时的参考版本被设计为在使用多个解析器线程时是安全的(只要使用多个解析器实例)。我维护了一个 ANTLR 4 的替代(非官方)分支,它以不同的方式实现核心算法,以提高多线程场景中的性能。

这个分支在某些领域公开了一个稍微不同的 API,所以它不是 ANTLR 4 4.0 版本的直接替代品。

https://github.com/sharwell/antlr4/tree/optimized

于 2013-03-23T21:03:52.400 回答