例外を使用して境界チェックを実行するとどうなりますか?
null チェック、境界チェック、ファイル存在チェックなどの処理操作に例外を使用すると、例外がスローされるたびに多くのオーバーヘッドが発生します。
単純に境界をチェックした場合、次のようになります。
例外ベースのチェックを使用するときに実際に行っていること:
- 配列の境界をチェックする
- Java 例外メカニズムを開始します (すべてのオーバーヘッドを含む)
- 新しい例外オブジェクトを作成する
- スタック トレース全体をダンプする
- 新しく作成されたオブジェクトをすべてのスタック データで埋める
- 例外をキャッチ
- 結果を返す
性能比較
この簡単なテスト プログラムを使用して、両方のタイプの配列境界チェックの速度を測定しました。
public class BoundsCheckTest {
final static int[] array = new int[1];
final static Random gen = new Random();
public static void main(String[] args){
boolean ret = false;
int tries = 100000000;
long timestart = System.nanoTime();
for (int a=0; a< tries; a++) {
ret = method1();
}
long timeend1 = System.nanoTime();
System.out.println();
for (int a=0; a< tries; a++) {
ret = metod2();
}
long timeend2 = System.nanoTime();
System.out.println();
long t1 = timeend1-timestart;
long t2 = timeend2-timeend1;
System.out.println("\ntime 1=["+t1+"]\n 2=["+t2+"]"+
"\ndiff=["+Math.abs(t1-t2)+"] percent diff=["+(100d*t2/t1-100)+"]");
}
private static boolean metod2() {
try {
int val = array[gen.nextInt(2)];
return true;
} catch (Exception e) {
return false;
}
}
private static boolean method1() {
return array.length < gen.nextInt(2);
}
}
結果:
JDK 7、日食Run as
モード:
time check=[911620628]
exc=[1192569638]
diff=[280949010] percent diff=[30.818632375220886]
JDK 7、日食Debug
モード:
time check=[931243924]
exc=[651480777121]
diff=[650549533197] percent diff=[69858.12378809143]
デバッグを無効にした場合の速度の低下は、目に見えるものではありますが、それほど重要ではありません。例外のないコードは、約 30% 高速です (false リターンの約 50% に対して)。デバッグモードでの速度低下は驚くべきものです。例外ベースのコードは、通常の単純な配列サイズ チェックよりも約 700 倍遅く実行されます。
例外の哲学
例外の背後にある一般的な考え方は、例外条件を処理する方法を許可することです。この場合、例外的な条件はまったくありません。範囲チェックは、コードの通常の部分にすぎません。その理由だけで、この状況では例外を使用しないでください。