2

最近私はこのようなものを書きました:

public void doSomething(boolean b1, boolean b2){
   while(true){
      if(b1){
         doThis();
      }
      if(b2){
         doThat();
      }
   }
}

しかし、すべての反復で2つのブール値をチェックする必要があるため、このソリューションは本当に好きではありません。したがって、可能な解決策として、各ループの前にifsを使用して4つのwhileループを作成することを想像できますが、明らかな理由から、これは保守性を損ないます。このコードを素晴らしく効果的にするための提案はありますか?

4

6 に答える 6

15

これは時期尚早の最適化のように見えます。

これはマインドトラップです。

アプリケーションが完成して修正されるまで、このような詳細について心配する必要はありません。次に、速度が十分でない場合は、プロファイラーを取り出して、プログラムの時間がどこで費やされているかを確認します。

おそらく注目に値しないものを最適化する精神的な努力を無駄にしないでください。

于 2012-12-14T17:59:50.653 に答える
9

パフォーマンスの観点からは、メソッド内で変更されないためb1分岐予測やJITコンパイルによってテストが最適化され、実際の状態チェックによってそのメソッドのパフォーマンスが低下することはほとんどありません。 。b2

あなたの代わりにif(b1)あなたが持っていたならif(getB1())、改善の余地があるかもしれません。

于 2012-12-14T18:02:52.507 に答える
4

CPU設計者は、これについてすでに考えています。これは分岐予測と呼ばれます。これが行うことは、通常は呼び出されないブランチを効果的にスキップすることです。これは、CPUが、パフォーマンスにほとんど影響を与えずに使用されていないブランチを動的に削除することを意味します。これの唯一の影響は、「ロールバック」が複雑になる可能性があるため、予測が間違っている場合です。あなたの場合、ブール値は変わらないので、問題は発生しないはずです。

于 2012-12-14T20:43:58.580 に答える
1

これは時期尚早の最適化であることに同意しますが、言語に短絡評価が保証されている場合に使用できる可能性のある別の構成があります。voidjavaではリターンタイプをにキャストできないため、を変更して返すboolean必要があります。doThis()doThat()boolean

public void doSomething(boolean b1, boolean b2){
    while(true){
        b1 && doThis(),
        b2 && doThat();
    }
}

(x && foo())、の値xがtrueの場合にのみ関数を実行します。それ以外の場合は、短絡評価が開始されます。

実際には値が割り当てられていないため、コンパイラがこの式全体を最適化するだけではないことに非常に注意する必要があります。

すべての場合に両方の比較を回避する実際の可能な最適化は、内部ループでswitchステートメントを使用することです。

public void doSomething(boolean b1, boolean b2){
    int state = (b1 ? 1 : 0) + (b2 ? 2 : 0);
    while(true){
        switch (state){
            case 1: doThis(); break;
            case 3: doThis();
            case 2: doThat();
            default:
        }
    }
}
于 2012-12-14T18:09:44.640 に答える
0
public void doSomething(boolean b1, boolean b2){
   while(true){
      if(b1 && b2)  
      {  
        doThis();  
        doThat();  
      }
      else if(b1){
         doThis();
      }
      else if(b2){
         doThat();
      }

   }
}

コンパイラはこれを最適化し、ループ内のif /elseifブロックごとにヒットしません。switchステートメントに似ています。潜在的なロジックを調べて、b1andb2がtrueの場合、およびを実行しdoThisますdoThat。それ以外の場合は、それぞれ1つだけが真であり、ロジックは以前と同様です。

于 2012-12-14T17:55:10.670 に答える
-4

ifステートメントをwhileの外に移動できると思います。

if (b1) {
    while (true) {
        doThis();
    }
}
if (b2) {
    while (true) {
        doThat();
    }
}

ただし、whileループを繰り返す条件を評価する必要があり、元のコードの2倍の頻度でそれを実行する必要があるため、実際には何も得られません。

于 2012-12-14T17:59:42.400 に答える