4

次の2つのコード例を検討してください。

例1。

public void setValue(int value)
{
    mValue = value;
}

例2。

public void setValue(int value)
{
    if (mValue != value)
    {
        mValue = value;
    }
}

すべての常識を超えて、いくつかのJavaコードを絶対最大値に最適化するように任務を負ったとしましょう。

2番目のコード例は最初のコード例の最適化でしょうか?つまり、JavaまたはJVMの最下位レベルでのif条件チェックとint割り当ての間に(どんなに小さなものであっても)違いはありますか?

4

4 に答える 4

9

2つ目は、最新のプロセッサでは分岐にコストがかかる傾向があるため、最適化に反する可能性があります(主に、分岐の予測ミスは非常にコストがかかるため)。

確実に見つける唯一の方法は、代表的な入力でコードをプロファイリングすることです。Javaで正しいマイクロベンチマークを作成するにはどうすればよいですか?を参照してください。意味のあるマイクロベンチマークを設定する方法に関するいくつかの指針について。

問題のコードが全体のCPU時間のかなりの部分を占めていない場合、世界中のすべての最適化がアプリケーションの全体的なパフォーマンスに大きな違いをもたらすことはないことに注意してください。

于 2013-01-05T20:33:13.140 に答える
3

NPEには良いアドバイスがあります。私が追加する1つのコメントは、おそらくmValue揮発性であるかどうか、およびそれを実行しているハードウェアにも依存するということです。揮発性物質の場合、書き込みは読み取りよりも数倍高くなる可能性があります。いくつかのハードウェア(たとえば、多くのモバイルデバイス)は、揮発性の読み取りが安価とはほど遠いため、違いはおそらく減少します。

于 2013-01-05T20:42:43.387 に答える
1

両方をコンパイルしてから、Javaバイトコード逆アセンブラを使用して違いを確認することができます。ウィキペディアのJVM命令リストは、開始するのに適した場所かもしれません。

私が使用したコンパイラとVMについて私が理解していることから、2番目のコードスニペットは、余分な比較操作のために(わずかに)少し遅くなる可能性があります。

JVM実装にオプティマイザーがある場合、最初のコードサンプルを1回の操作に減らすことができる可能性がありますが、2番目のスニペットでは比較操作を説明するために少なくとも1回または2回の操作が必要になります。

于 2013-01-05T20:36:39.187 に答える
0

優れたコーディング手法によると、「最後の瞬間までに最適化を遅らせる」

しかし、コードテストは次のように述べています。

  • TOTAL(1)= 1000000000 1420ms TOTAL(2)= 1000000000 2155ms
  • TOTAL(1)= 1000000000 1374ms TOTAL(2)= 1000000000 1884ms
  • TOTAL(1)= 1000000000 1379ms TOTAL(2)= 1000000000 2072ms

比較と設定は良くありません。

// Test Code
public class CompareAndSet {
    int mValue;

    // 1
    public void setValue1(int value) {
        mValue = value;
    }

    // 2
    public void setValue2(int value) {
        if (mValue != value) {
            mValue = value;
        }
    }

    public static void main(String[] args) {
        final int TOTAL = (int) 1e9;
        long ts;
        for (int j = 0; j < 3; j++) {
            // 1
            {
                ts = System.currentTimeMillis();
                CompareAndSet cs = new CompareAndSet();
                for (int i = 0; i < TOTAL; i++) {
                    cs.setValue1(i);
                }
                System.out.println("TOTAL(1)=" + TOTAL + " "
                        + (System.currentTimeMillis() - ts) + "ms");
            }
            // 2
            {
                ts = System.currentTimeMillis();
                CompareAndSet cs = new CompareAndSet();
                for (int i = 0; i < TOTAL; i++) {
                    cs.setValue2(i);
                }
                System.out.println("TOTAL(2)=" + TOTAL + " "
                        + (System.currentTimeMillis() - ts) + "ms");
            }
        }
    }

}
于 2013-01-05T20:52:17.500 に答える