アプリケーションの起動時に .NET JIT コンパイラーに最も最適化されたコードを強制的に生成する
-
09-09-2019 - |
質問
私は C# で DSP アプリケーション (基本的にはマルチトラック エディター) を作成しています。私はさまざまなマシンでかなり長い間プロファイリングを行ってきましたが、いくつかの「興味深い」ことに気づきました。
私の自宅のマシンでは、再生ループの最初の実行が利用可能な時間の約 50% ~ 60% を占め (JIT が機能しているためだと思います)、その後のループでは安定した 5 時間まで下がります。 % 消費。問題は、アプリケーションを遅いコンピュータで実行すると、最初の実行に利用可能な時間を超えてしまい、再生が中断され、出力オーディオが乱れてしまうという、容認できないことです。その後は 8% ~ 10% の消費に下がります。
最初の実行後も、アプリケーションは時間のかかるルーチンを時々 (2 秒ごとにほぼ 2 秒ごとに) 呼び出し続けるため、安定した 5% の消費量が 20% ~ 25% という非常に短いピークに達します。アプリケーションをしばらく実行すると、これらのピークも 7% ~ 10% に低下することに気付きました。(コードのこれらの部分を再コンパイルする JIT が原因かどうかはわかりません)。
つまり、JIT には深刻な問題があります。アプリケーションは非常に遅いマシンでも正常に動作しますが、このような「コンパイルの嵐」は大きな問題になります。私はこの問題を解決する方法を見つけようとしていて、すべての「賢明な」ルーチンを、起動時に事前に「圧縮」するようにアプリケーションに指示する属性でマークするというアイデアを思いつきました。 , そのため、本当に必要なときに完全に最適化されます。しかし、これは単なるアイデアであり (私もあまり好きではありませんが)、問題全体に対するより良い解決策があるのではないかと考えています。
皆さんの意見を聞きたいです。
(アプリケーションの NGEN はオプションではありません。私は入手できるすべての JIT 最適化が好きであり、それを望んでいます。)
編集:
メモリ消費とガベージ コレクション キックは問題ではありません。私はオブジェクト プールを使用しており、再生中のメモリの最大ピークは 304 Kb です。
解決
アプリケーションの初期化ルーチン中に、JIT コンパイラをトリガーしてアセンブリのセット全体をコンパイルできます。 PrepareMethod
...メソッド (使用する必要はありません) NGen
).
このソリューションについては、ここで詳しく説明します。 実行時に JIT コンパイルを強制する.
他のヒント
初期速度は確かに Fusion+JIT のように聞こえますが、これは ILMerge (Fusion の場合) と NGEN (JIT の場合) によって助けられます。起動時にシステムを通じて常にサイレントトラックを再生して、ユーザーが歪みに気付かずにすべての難しい作業を実行できるようにすることはできますか?
NGEN は良い選択肢です。ありますか 理由 使えないの?
あなたが言及した問題 後 初期ロードは行う ない JIT に関連しているようです。おそらくガベージコレクションでしょう。
プロファイリングを試してみましたか?CPU とメモリ (コレクション) の両方?
Marc が述べたように、進行中のスパイクは JIT の問題とは思えません。他に探すべきこと:
ガベージ コレクション - オーディオ処理中にメモリを割り当てていますか?大量のガベージを作成している場合、または Gen 0 コレクションでも生き残るオブジェクトを作成している場合は、顕著なスパイクが発生する可能性があります。ある種の事前割り当てを行っているように見えますが、ライブラリ コード内の隠れた割り当てに注意してください (foreach ループでも割り当て可能です)。
デノーマル。特定のタイプのプロセッサでは、非常に小さな浮動小数点数を処理するときに問題が発生し、CPU スパイクが発生する可能性があります。見る http://www.musicdsp.org/files/denormal.pdf 詳細については。
編集:
NGen を使用したくない場合でも、少なくとも NGen 化されたバージョンを比較して、JIT によってどのような違いが生じるかを確認してください。
JIT の影響を受けていると思われる場合は、NGEN を使用してアプリをプリコンパイルし、テストを再度実行します。NGEN によってコンパイルされたコードには JIT オーバーヘッドはありません。NGEN で処理されたアプリで依然としてスパイクが見られる場合は、それらが JIT によって引き起こされたものではないことがわかります。