メモリを節約できるように、配列の配列ではなく多次元の配列を作成するコードを書きました。それから、いくつかのテストを実行して、通常のJava配列配列(int [] [])と速度を比較しました。メモリを節約してもプログラムの実行速度を遅くしたくないからです。私がタイミングテストで見たものは、私が混乱しています。テスト実行の典型的な結果を以下に示します。時は同じコードのものです。最後の2つが最初の4つよりもはるかに大きいことに注目してください。私は理解できないJavaのパフォーマンスの問題があります
時間:58343722 NS
時間:59451156 NS
時間:51374777 NS時間:61777424 NS
時間:813156695 NS
時間:今782140511のNS
私が最初に思ったのは、ガベージコレクタが何を蹴っているのかということでした。メモリ制限を5GB(-Xmx5g)に上げて、ガベージコレクタが挑戦的に始まらない。何も変わっていません。私は物事を動かしましたが、パターンはそのままです。
パターンとは何ですか?最初の3回では、コードの一部は関数内にあり、私はそれを3回呼び出します。 2番目の3回では、コードのビットが1回の関数で3回繰り返されます。コードのビットが同じ関数で複数回実行されるたびに、コードのビットを実行するのにかかる時間は、コードの2番目のビットから始まり、そこにとどまるというパターンです。
私はこのような結果を生む1つの改変を見つけた:
時間:58729424 NS
時間:59965426 NS
時間:51441618 NS時間:57359741のNS
時間: 65362705 ns
時間:857942387 ns
私がしたことは、2番目の3つのコードビットの間に1ミリ秒の遅延を追加することでした。これを行うと、ブロック内のコードビットの秒が高速化され、遅れてもコードビットの速度が上がることはありません。
率直に言って、私は混乱しています。私はこの行動を説明することはできません。誰かが何が起こっているかについていくつかの光を当てることができますか?
package multidimensionalarraytests;
import java.lang.reflect.Array;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MultidimensionalArrayTests {
static ArrayInt2Dv1 array=new ArrayInt2Dv1(10000,10000);
public static void main(String[] args) {
System.out.println("ignore the warmup");
test();
test();
combined();
combined();
System.out.println("running tests");
test();
test();
test();
System.out.println();
combined();
}
static long test(){
int value=1;
long start,stop,time;
System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");
return time;
}
static void combined(){
int value=1;
long start,stop,time;
System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");
//try {Thread.sleep(1);} catch (InterruptedException ex) {}
System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");
//try {Thread.sleep(60000);} catch (InterruptedException ex) {}
System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");
}
}
と::オプション-Xms5g -Xmx5g -XXれたWindows 7上の
package multidimensionalarraytests;
public class ArrayInt2Dv1 {
int [] array;
public final int length1;
public final int length2;
public ArrayInt2Dv1(int length1, int length2){
this.length1=length1;
this.length2=length2;
array=new int[length1*length2];
}
public int get(int x,int y){
return array[x*length2+y];
}
public void set(int x,int y,int value){
array[x*length2+y]=value;
}
}
---編集---
出力ここ
はコードです: + PrintCompilation -verbose:gc -XX:CICompilerCount = 1 -Xbatch
time: 299 1 b multidimensionalarraytests.ArrayInt2Dv1::set (15 bytes)
302 2 b multidimensionalarraytests.ArrayInt2Dv1::get (14 bytes)
303 1 % b multidimensionalarraytests.MultidimensionalArrayTests::test @ 31 (114 bytes)
358 1 % multidimensionalarraytests.MultidimensionalArrayTests::test @ -2 (114 bytes) made not entrant
60671451 ns
359 3 b multidimensionalarraytests.MultidimensionalArrayTests::test (114 bytes)
time: 365 2 % b multidimensionalarraytests.MultidimensionalArrayTests::test @ 31 (114 bytes)
58104484 ns
time: 425 3 % b multidimensionalarraytests.MultidimensionalArrayTests::combined @ 31 (330 bytes)
69008251 ns
time: 806898159 ns
time: 845447596 ns
2146 4 b multidimensionalarraytests.MultidimensionalArrayTests::combined (330 bytes)
time: 52493169 ns
time: 804304528 ns
time: 845500191 ns
running tests
time: 51290771 ns
time: 51922285 ns
time: 51264108 ns
time: 52258679 ns
time: 842229025 ns
time: 871403625 ns
同じオプションを持つLinuxの(同じマシン上のVirtualBox上のUbuntu)で10
:
283 1 b java.lang.String::hashCode (60 bytes)
285 2 b sun.nio.cs.UTF_8$Encoder::encodeArrayLoop (490 bytes)
287 3 b java.lang.String::charAt (33 bytes)
287 4 b java.lang.String::indexOf (151 bytes)
297 5 b java.io.UnixFileSystem::normalize (75 bytes)
2850 6 b java.lang.String::lastIndexOf (156 bytes)
ignore the warmup
time: 5885 7 b multidimensionalarraytests.ArrayInt2Dv1::set (15 bytes)
5948 8 b multidimensionalarraytests.ArrayInt2Dv1::get (14 bytes)
5949 1% b multidimensionalarraytests.MultidimensionalArrayTests::test @ 31 (114 bytes)
11529998483 ns
17565 9 b multidimensionalarraytests.MultidimensionalArrayTests::test (114 bytes)
time: 1619622928 ns
time: 19718 2% b multidimensionalarraytests.MultidimensionalArrayTests::combined @ 31 (330 bytes)
475786382 ns
time: 288586857 ns
time: 315560700 ns
20789 10 b multidimensionalarraytests.MultidimensionalArrayTests::combined (330 bytes)
time: 460577230 ns
time: 311525066 ns
time: 312343429 ns
running tests
time: 310261854 ns
time: 298826592 ns
time: 304689920 ns
time: 315416579 ns
time: 299473245 ns
time: 290211350 ns
まずは、http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – NPE
をご覧ください。上記のコードを変更して推奨事項を反映させ、-Xms5g -Xmx5g -XX:+ PrintCompilation -verbose:gc -XX:CICompilerCount = 1 -Xbatchというオプションでプログラムを実行しました。しかし、それは有意に結果を変えなかった。 – user1145922
私は(更新されたコードで)試しましたが、Java 6u26を64ビットUbuntuで使用してエフェクトを再現することはできません。ここでは、6つの経過時間はお互いに10%以内です(ウォーミングアップ時間はジャストインタイムコンパイラが蹴り込むため変動します)。 – NPE