今まで作ったソースを実行するとバッファ処理に時間がかかっていました。修正することによって早くなるようでしたら修正したいと思います。その前に検証をして見ましょう。
1. 現在の実装
バッファリングをする処理に可変の配列を使っている箇所があるとします。ArrayListクラスにバッファするものを一度に2回addして、バッファされているうちはそれを読み出す、という処理です。これを引数の回数分繰り返すことにします。
public static void byCase1(long count){ ArrayList buffer = new ArrayList<>(); for(long i = 0;i < count;i++){ buffer.add(0d); buffer.add(1d); while(!buffer.isEmpty()){ double value = buffer.remove(0); } } }
可変配列の長さを買えながら処理を行うのは時間的にコストがかかるようです。これをなんとかしたいと思います。
2. キューを使った実装
JavaのAPIにはキューのクラスがあるのでこれを利用して見ます。同じ処理を以下のように書きました。作りはほぼ変わりません。少しは早くなると良いと思います。
public static void byCase2(long count){ ArrayDeque buffer = new ArrayDeque<>(); for(long i = 0;i < count;i++){ buffer.add(0d); buffer.add(1d); while(!buffer.isEmpty()){ double value = buffer.remove(); } } }
3. プリミティブな配列を使った実装
配列の長さを変えずに位置情報(変数index)を書き換える処理で作りました。
public static void byCase3(long count){ double[] buffer = new double[2]; int index; for(long i = 0;i < count;i++){ buffer[0] = 0d; buffer[1] = 1d; index = 0; while(index < buffer.length){ double value = buffer[index]; index++; } } }
比較する
それぞれのケースでどれだけ時間がかかるか計測します。それぞれ10億回ずつ繰り返してどのくらい時間がかかるか見て見ます。
long count = 1000000000; long time; time = System.currentTimeMillis(); byCase1(count); long time1 = System.currentTimeMillis() - time; time = System.currentTimeMillis(); byCase2(count); long time2 = System.currentTimeMillis() - time; time = System.currentTimeMillis(); byCase3(count); long time3 = System.currentTimeMillis() - time; System.out.println("case1=" + time1); System.out.println("case2=" + time2); System.out.println("case3=" + time3);
以下結果です。単位はミリ秒ですからそれぞれ25秒、14秒弱、0.9秒となりました。キューを使っても半分近くに短縮できますが、プリミティブな配列を使ったものが群を抜いて速いことがわかりました。
case1=25085 case2=13728 case3=878
これは実装に生かす必要があります。