10

大量の継続的なガベージコレクションと競合しながら、何かがどのように機能するかをベンチマークすることを検討しています。以前、安定したシングルスレッドの実行でどのように動作するかをベンチマークしましたが、今度は、よりストレスの多いJVMで同じテストを実行したいと思います。基本的に、適度に一貫したペースでオブジェクトを作成および破棄するバックグラウンドスレッドが必要です。

安定しているがGCを多用する操作を実装する方法についての提案を探しています。いくつかの目標を達成する必要があります。

  • GCでかなりの時間(たとえば、20〜50%)を費やします
  • 時間の経過とともにほぼ一定量の作業を行い、GCに対して同様に一定量の作業を作成します
  • ヒープをフラッディングしてJava heap spaceエラーをトリガーしないようにします
  • GCに過負荷をかけたり、GC overhead limit exceededエラーを引き起こしたりしないでください
4

1 に答える 1

13

安定した量のガベージコレクションを引き起こす可能性のあるものに独自のパスを実装しました。完全なコードはここから入手できます:https ://gist.github.com/dimo414/5243162

重要なのは、これら2つの方法であり、(スレッド時間やCPU時間ではなく)特定の期間に多数のオブジェクトを構築して解放します。

/**
 * Loops over a map of lists, adding and removing elements rapidly
 * in order to cause GC, for runFor seconds, or until the thread is
 * terminated.
 */
@Override
public void run() {
    HashMap<String,ArrayList<String>> map = new HashMap<>();

    long stop = System.currentTimeMillis() + 1000l * runFor;
    while(runFor == 0 || System.currentTimeMillis() < stop) {
        churn(map);
    }
}

/**
 * Three steps to churn the garbage collector:
 *   1. Remove churn% of keys from the map
 *   2. Remove churn% of strings from the lists in the map
 *      Fill lists back up to size
 *   3. Fill map back up to size
 * @param map
 */
protected void churn(Map<String,ArrayList<String>> map) {
    removeKeys(map);
    churnValues(map);
    addKeys(map);
}

クラスは実装されRunnableているため、独自のバックグラウンドスレッドで(または一度に複数)開始できます。指定する限り実行されます。または、必要に応じてデーモンスレッドとして開始し(JVMの終了を停止しないように)0、コンストラクター引数として秒を使用して永久に実行するように指定できます。


このクラスのベンチマークを行ったところ、ブロッキング時間の3分の1近く(おそらくGCで)が費やされ、15〜25%のチャーンと約500のサイズのおよその最適値が特定されました。各実行は60秒間行われ、以下のグラフは、によって報告されたスレッド時間と、によって報告さjava.lang.managment.ThreadMXBean.getThreadCpuTime()れたスレッドによって割り当てられた合計バイト数をプロットしていますcom.sun.management.ThreadMXBean.getThreadAllocatedBytes()

解約率ベンチマーク

コントロール(0%チャーン)は本質的にGCを導入するべきではなく、ほとんどオブジェクトを割り当てず、その時間のほぼ100%をスレッドに費やしていることがわかります。5%から95%のチャーンまで、時間の約3分の2がスレッドに費やされ、おそらく残りの3分の1がGCに費やされていることがかなり一貫して見られます。妥当な割合だと思います。興味深いことに、解約率の非常に高いエンドでは、スレッドでより多くの時間が費やされていることがわかります。おそらく、GCが非常にクリーンアップしているため、実際にはより効率的になる可能性があります。約20%は、各サイクルでかき回すオブジェクトの適切な数のようです。

データサイズベンチマーク

これは、マップとリストのさまざまなターゲットサイズでスレッドがどのように機能するかをプロットします。サイズが大きくなると、GCで費やす時間が長くなることがわかります。興味深いことに、データサイズが大きいと割り当てられないオブジェクトが少なくなるため、実際には割り当てられるオブジェクトが少なくなります。同じ期間にできるだけ多くのループを作成します。JVMが処理する必要のあるGCチャーンの量を最適化することに関心があるため、できるだけ多くのオブジェクトを処理し、作業スレッドで費やす時間をできるだけ少なくする必要があります。多数のオブジェクトを生成し、GCにかなりの時間を費やすため、4〜500前後が適切なターゲットサイズのようです。

これらのテストはすべて標準java設定で行われたため、ヒープを操作すると異なる動作が発生する可能性があります。特に、ヒープがいっぱいになる前に設定できる最大サイズは約2000でした。これを大きくすると、さらに良い結果が得られる可能性があります。ヒープのサイズを大きくした場合のサイズ。

于 2013-03-26T05:09:24.007 に答える