多くの人が以前にこの質問をしたことは知っていますが、私の焦点はパフォーマンスではなく、操作のメモリ フットプリントです。
次のダミー クラスを検討してください。
public class MemoryDemo implements Runnable{
private boolean run;
public MemoryDemo(){
run = true;
}
@Override
public void run(){
byte[] wbuffer; //Here
final int n = ... //Some big quantity in order of millions.
while(run){
//byte[] wbuffer; or here?
wbuffer = new byte[n]; //Reallocate every loop? or just keep the same memory?
//Do stuff with the byte array here
//Copies the data to the target buffer (Not shown here, from another class)
System.arraycopy(wbuffer, 0, n, targetbuffer, 0, wbuffer.length);
}
}
}
私はあちこちから知っていますが、パフォーマンスに関してはまったく違いがなく、範囲を限定する方が良いと人々は言っていますが、メモリフットプリントはどうですか?
上から観察すると、かなり大きな配列を割り当てていることがわかります.Javaには削除関数/構造がないため、メモリを解放するにはガベージコレクターに頼る必要があります. 私のアプリケーションには、これらのループ (基本的にはリアルタイムの画像処理パイプライン) がいくつかあります。メモリ フットプリントをできるだけ最小限に抑えようとしています (つまり、GC が最適な方法でジョブを実行できるようにします)。
ガベージ コレクションの観点から、ループ内とループ宣言外のどちらが優れているか。GC はメモリへの参照がなくなった場合にのみメモリを解放できることは知っていますが、変数を再割り当てするとどうなるか (つまり、ループが再起動してwbuffer
オブジェクトが再度割り当てられるとき) は不明です。内部ループ変数はその参照全体を失うので、最初にガベージコレクションを取得しますか? それとも、変数が再割り当てされると、両方ともガベージコレクションされますか? System.gc();
すべてのループの最後に呼び出す必要がありますか?
また、コードがバイト配列内のすべてのバイトに書き込むことができると仮定すると、変数を再割り当てしない場合 (ループ内で new byte[n] を呼び出さない場合と同様)、バイト配列を再割り当てするよりも良いアプローチ (より醜い1つも...)?
NB配列を再割り当てしないことは、私にとって(すべてのクラスにとって)実行可能なオプションではない可能性があります。それが最良のオプションであることが判明した場合、どちらが2番目に優れているか(ループの内側/外側または違いなし)も説明してください!