2

そこにあるJVMのいくつかは、境界チェックを削除することでコードの実行を最適化できることを読みました。私が理解しようとしているのは、どのコーディング手法がより効果的に機能するかということです。

以下のメソッドexample1では、JVMはそれを理解し、 source [index]参照の境界チェックを排除しますか?

example2はより良いコードプラクティスですか?そう思われるかもしれませんが、ループ内の一部のアルゴリズムでは、インデックスが範囲外になっているのは正常な状態です。したがって、そのループ内で大量のExceptionオブジェクトを生成する必要はありません。

public void example1(int [] source, int index) {
    if (index >= 0 && index < source.length)
        System.out.println("Value is " + source[index]);
    else 
        System.out.println("Out of range: " + index);
}

public void example2(int [] source, int index) {
    try {        
        System.out.println("Value is " + source[index]);        
    } catch (IndexOutOfBoundsException exp) {
        System.out.println("Out of range: " + index);
    }
}

これらのコードフラグメントは、単なる表現です。これらの例では、境界チェックがパフォーマンスにほとんど影響しないことを認識しています。ただし、冗長境界チェックが追加される組み込みプロトコルアプリケーションに取り組んでいます。

4

2 に答える 2

5

最初の質問に対して、example1では、境界チェックは理論的に排除できます。最新のJITコンパイラーがこれを実行することを期待します(たとえば、source [index]が展開されるときの境界チェックでの共通部分式除去を介して)。いつものように、これは実装に依存するため、信頼することはできません。境界チェックが削除されていない場合でも、OTOHの違いは些細なことです。つまり、source.lengthのキャッシュされたメモリ位置に到達し、整数の比較をいくつか実行するため、オーバーヘッドはごくわずかです。

example2は良い習慣ではありません。例外が発生しましたが、それをキャッチして、何も起こらなかったかのように続行します。stdoutを注意深く見ていなければ、コードにバグがあるという事実を完全に見逃す可能性があります。

「インデックス」の有効な入力と見なすものに応じて、基本的に2つの一般的な「適切な」可能性があります。

  1. 範囲外のインデックス値が予期され、有効な入力と見なされます。この場合、example1のように明示的にテストして処理する必要があります。この場合、いかなる種類の例外もスローする必要はありません。

  2. 範囲外のインデックスは予期しないものです(したがって、呼び出し元のコードのバグです)。あなたのコードはここで例外を発生させるはずです。必要に応じて、独自のメッセージで例外をキャッチして再スローできますが、IndexOutOfBounds例外を伝播させることもできます。この例外処理のパフォーマンスへの影響について心配する必要はありません。バグを発見したばかりなので、プログラムをできるだけ早く「大音量で」失敗させたいと考えています。

于 2011-07-03T16:25:10.617 に答える
1

インデックスが範囲外であることが通常の状態になる可能性があることはわかりません。アルゴリズムにバグがあるか、入力を正しく検証していません。この場合、入力の検証は、インデックスが境界内にあることを確認することで構成されます。(最初のスニペットのように) でチェックするif方が、例外をキャッチするよりもはるかに読みやすく、クリーンで効率的です。

于 2011-07-03T16:26:36.607 に答える