我正在使用 ANTLRv4 生成的解析器来处理具有多核机器上的大量文件。为了获得一些额外的速度,我想并行处理文件。
为了检查解析器性能是否受 CPU 限制,我将文件分成组,并使用独立进程解析它们,每个进程在专用 JVM 实例中运行相同的解析器。这大大提高了性能。
这鼓励我尝试使用多个线程而不是进程进行相同的尝试,但是没有成功。我创建了两个工作线程,每个线程都有自己的解析器、词法分析器和文件流实例。返回的结果是正确的,但是,使用两个线程实际上比使用一个线程花费的时间稍长。
为了确保我正确使用线程并且 JVM 安装没有问题,我暂时将解析代码替换为计算斐波那契序列的代码:在这种情况下,使用多个线程会提高性能。
分析这种行为,我发现当使用多个解析线程时,没有一个 CPU 达到高使用率。看起来线程正在争夺一些共享资源。
看了一下ANTLR源代码,在ParserATNSimulator.java中发现如下注释:
“同一个解析器的所有实例通过一个静态字段共享相同的决策 DFA。每个实例都有自己的 ATN 模拟器,但它们共享相同的 decisionToDFA 字段。它们还共享一个 PredictionContextCache 对象,确保所有 PredictionContext 对象在 DFA 之间共享状态。这有很大的不同。
我想知道对这些共享资源的同步访问是否会导致性能问题。如果是这样,是否有可能创建这些资源的唯一实例?或者是否有更简单的解决方案?
提前致谢!
费边