5

j=k*l最初の 3 つのグループは同じであるのに、グループとm=n*oのパフォーマンスが異なるのはなぜですか?

int a = 42;
int b = 42;
int c = 42;

Integer d = 42;
int e = 42;
int f = 42;

int g = 42;
Integer h = 42;
int i = 42;

int j = 42;
int k = 42;
Integer l = 42;

Integer m = 42;
Integer n = 42;
Integer o = 42;

for(int z = 0; z < 1000000000; z++){
    // c = a*b; // 630 ms
    // f = d*e; // 630 ms
    // i = g*h; // 630 ms
    // l = j*k; // 6000 ms
    // o = m*n; // 6400 ms
}
4

7 に答える 7

6

何も役に立たないループがあります。そのため、JITはこれを検出してループを排除するのに時間がかかる場合があります。最初の4つの例では、コードは平均して1クロックサイクルの何分の1かを取っています。これは、ループが最適化されており、ループを検出して何もない状態に置き換えるのにかかる時間を実際に測定していることを示す強力なヒントです。

後の例では、JITが排除しないループについて何かがあるため、ループは最適化されていません。それはオブジェクトの割り当てだと思いましたが、Integerオブジェクト-verbosegcが作成されていないことを示しました。

私のマシンでは、ループは約1.9 nsまたは約6クロックサイクルかかります。これはかなり速いので、何が残っているのかわかりません。これにはそれほど時間がかかります。

于 2013-01-28T08:27:27.167 に答える
4

サイクルで新しいオブジェクトを作成するには、常にコストがかかります。最後の2つの例では、パフォーマンスコストが高いサイクルで新しい整数オブジェクトを作成しました。プリミティブはスタックに格納され、オブジェクトはヒープに格納されます。何かをスタックに入れる方が、ヒープに入れるよりも安価です。

于 2013-01-28T08:21:00.447 に答える
4

基本的に、これは JVM 内で起こっていることであり、パフォーマンスの問題を引き起こしています。

c = a*b; // 630  ms -> No boxing and unboxing
f = d*e; // 630  ms -> Unboxing d
i = g*h; // 630  ms -> Unboxing h
l = j*k; // 6000 ms -> Creates a new Integer object L, and assign J * K to L
o = m*n; // 6400 ms -> Creates a new Integer object 0, unbox m and n for calculation and assign m * n to o

言い換えると

l = j*k; // 6000 ミリ秒は以下のコードに相当します

temp = j*k;
Integer l = new Integer(temp); 

o = m*n; // 6400 ミリ秒は以下のコードと同等です

temp = j.intValue() * k.intValue();
Integer l = new Integer(temp); 

最後の 2 つのステートメントは、1000000000不要なIntegerオブジェクト (ループ カウント) を作成します。これは明らかにパフォーマンスの低下になります。

于 2013-01-28T08:32:36.370 に答える
1
  1. 整数オートボックスのキャッシュが小さい
  2. オブジェクトの作成には少し時間がかかります

これを確認してください: java.lang.Integer.IntegerCache

于 2013-01-28T08:24:43.617 に答える
0

オブジェクトの作成にはオーバーヘッドがあります(または、他のコメントから、オブジェクトを作成するときに、オブジェクト内で何も行われていないため、ループを最適化できない可能性があります)。

int = int * int

関係するオブジェクトはありません。

int = Integer * intまたint = int * Integer

整数のintメンバーはintと乗算されるため、オブジェクトを作成する必要はありません。

Integer = int * int

結果から整数オブジェクトを作成する必要があります(遅い)。

Integer = Integer * Integer

2つのIntegerのintメンバーは乗算されますが、結果からIntegerオブジェクトを作成する必要があります(低速)。

于 2013-01-28T08:27:07.833 に答える
0

おそらくl = j * k、intを整数にボックス化する必要があるのに対し、c = a * bそうする必要はないからです。VMはループを最適化することもでき、1回の反復を実行すると、10億を実行した場合と同じ結果になることを理解しています。単純なマイクロベンチマークに注意してください。

于 2013-01-28T08:22:38.743 に答える
0
m = n*o  ==> Integer = Integer * Integer 

その間:

l = j*k ==> Integer = int * int // Integer is an object so autoboxing costs some performance here.
于 2013-01-28T08:23:05.693 に答える