ANTLRv4で生成されたパーサーを使用して、複数のコアを備えたマシンで大量のファイルを処理しています。速度を上げるために、ファイルを並行して処理したいと思います。
パーサーのパフォーマンスがCPUにバインドされているかどうかを確認するために、ファイルをグループに分割し、専用のJVMインスタンスで同じパーサーを実行する独立したプロセスを使用してファイルを解析しました。これにより、パフォーマンスが大幅に向上しました。
これにより、プロセスの代わりに複数のスレッドを使用して同じことを試すようになりましたが、成功しませんでした。2つのワーカースレッドを作成しました。それぞれに、パーサー、レクサー、ファイルストリームの独自のインスタンスがあります。返される結果は正しいですが、2つのスレッドを使用すると、実際には1つを使用するよりも少し時間がかかります。
スレッドを正しく使用し、JVMのインストールに問題がないことを確認するために、解析コードを一時的にフィボナッチ数列を計算するコードに置き換えました。この場合、複数のスレッドを使用するとパフォーマンスが向上します。
この動作を分析すると、複数の解析スレッドを使用している場合、どのCPUも使用率が高くならないことがわかりました。スレッドが共有リソースをめぐって争っているようです。
ANTLRソースコードを見てみると、ParserATNSimulator.javaに次のコメントがあります。
「同じパーサーのすべてのインスタンスは、静的フィールドを介して同じ決定DFAを共有します。各インスタンスは独自のATNシミュレーターを取得しますが、同じdecisionToDFAフィールドを共有します。また、すべてのPredictionContextオブジェクトがDFA間で共有されるようにするPredictionContextCacheオブジェクトも共有します。これは大きなサイズの違いになります。」
これらの共有リソースへの同期アクセスがパフォーマンスの問題を引き起こしているかどうか疑問に思っています。もしそうなら、代わりにこれらのリソースの一意のインスタンスを作成する可能性はありますか?それとも、問題に対するもっと簡単な解決策があるのでしょうか?
前もって感謝します!
ファビアン