JVM で実行するアプリケーション (ゲーム) があります。
ゲームの更新ロジック (毎秒 60 回実行) は、「タイム スライス」 (1/60 秒) の約 25% を使用して終了し、残りの 75% をスリープ状態にします。しかし、GC コレクターが実行されると、75 ~ 200% まで上昇し、残りの実行中はその状態が続きます。
ゲームは約 70Mb のヒープを使用し、約 1-2mb/s で成長します。GC が実行されると 70Mb に戻るため、真のメモリ リークはありません。将来的にはこの数値を下げるように努めますが、この範囲では問題にならないはずです。
ランタイム引数やフラグなしで JVM 8 を使用していますが、どの GC が私に与えるのかわかりません。
ヒープを別のサイズに設定してみましたが、この現象には影響しません。
これがなぜなのかについては、次の 2 つの理論があります。
GC は意図せずにヒープを断片化し、更新ループでキャッシュの破棄を引き起こします。データがループして更新されるため、データの近接性から大きな恩恵を受けるロジックがあります。一部のデータを古い領域にシャッフルし、一部を若い領域 (苗床) に保持している可能性がありますか?
突然の GC 処理が OS をトリガーし、メインの更新スレッドが現在ほど多くの CPU リソースを必要としないことを OS に認識させ、その優先度を下げます。(ただし、thread.sleep() をスキップして未使用の CPU 使用率からスリープしても現象は持続します。
どう思いますか。私の理論はもっともらしいですか、それらについて何かできることはありますか、それとも C 言語に切り替える必要がありますか? GC に関する私の知識は限られています。
PS 補足として、通常、update() はポスト GC の 75% で終了します。200% のような数値が得られるのは、VSync を使用している場合です。