こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

配列長参照のオーバーヘッド

for等ループでループ終了条件に配列長を使用する場合、配列長を毎回参照する場合と一旦変数に格納して参照する場合、定数を使用する場合と処理速度の差はありますか?

つまり
1、for( int i = 0; i < array.length; i++ ) { ... }
2、for( int i = 0; i < len; i++ ) { ... } *(int len=array.length)
3、for( int i = 0; i < 10; i++ ) { ... } *(int[] array = new int[10])

forループ内の処理のメモリ使用量の多寡は不明で、毎ループで読み取られる全ての変数はコンピュータのキャッシュに残るかどうかは不明だとします。

投稿日時 - 2010-11-23 18:50:44

QNo.6339209

困ってます

質問者が選んだベストアンサー

private static final int N = 100;
public static void main(String[] args) {
int[] x = new int[N];
int len = x.length;
for (int i = 0; i < x.length; i++) ; // (A)
for (int i = 0; i < len; i++) ; // (B)
for (int i = 0; i < N; i++) ; // (C)
}

から得られるバイトコードはjavapによれば以下のようになる(1.6.0_22にて)。

0: bipush 100
2: newarray int
4: astore_1

5: aload_1
6: arraylength
7: istore_2 // B-1

// (A)
8: iconst_0
9: istore_3
10: iload_3
11: aload_1 // A-1
12: arraylength // A-2
13: if_icmpge 22
16: iinc 3, 1
19: goto 10

// (B)
22: iconst_0
23: istore_3
24: iload_3
25: iload_2 // B-2
26: if_icmpge 35
29: iinc 3, 1
32: goto 24

// (C)
35: iconst_0
36: istore_3
37: iload_3
38: bipush 100 // C-1
40: if_icmpge 49
43: iinc 3, 1
46: goto 37

49: return

(A),(B),(C)ともにループ変数iはループ開始前に、
iconst_0
istore_3
iload_3
という形で3と番号付けられた局所変数に0で初期化され、次にそれをロードして終了条件判定に使用する片方の値とされる。
比較判定に使うもう一方の値はそれぞれ得る方法が異なり、
(A)の場合はループの脱出判定ごとに配列xへの参照を得て(A-1)、arraylength命令を呼び出す(A-2)。
(B)の場合はB-1でループ前にarraylength命令で得られた値を局所変数2(=len)に入れておき、ループの度にB-2でロードする。
(C)の場合は具体的な数値100を比較用に毎回VMのオペランドスタックに放り込む(C-1)。

つまり、
aload_1 // A-1
arraylength // A-2
するのと
iload_2 // B-2
するのと
bipush 100 // C-1
するのとどれがいいかの判断になる。
これらの速度はVMの実装でも変わってくるし、実行時最適化も関わってくるので、最終的には実測による判断になると思う。

ちなみに、配列のサイズは変更できないが、xが参照している配列オブジェクト自体が変わるかもしれないのでループごとにarraylength命令が発行されている。
コンパイラによってはコンパイル時にもう少し最適化されたコードを吐くかもしれない。
本家のコンパイラはコンパイル時の最適化よりも実行時最適化で何とかしようとする傾向があるみたいなので静的解析だけでは不十分。

投稿日時 - 2010-11-23 21:14:37

お礼

javapコマンドというのは初めて知りました。

私は回答を読んでいる祭にパターンAは2ステップだから不利だと安直に思いましたが、確かに最適化の関係から実測が重要ですね。
となるとやはり、特殊な場合を除きコードリーディングのし易さを優先した方がよさそうですね。

非常に知見を深められました。
感謝します。

投稿日時 - 2010-11-24 00:39:49

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

ないです。lengthはクラスの静的変数ですから。

投稿日時 - 2010-11-23 19:10:21

補足

ArrayList#size()はどうですか?

投稿日時 - 2010-11-23 20:28:02