2011-07-13 10 views
25

Java6では、プリミティブ配列とオブジェクト配列のそれぞれについて、quicksortとmergesortの両方がArrays#sortで使用されていました。 Java7では、これらは両方ともDualPivotQuicksortとTimsortに変更されています。新しいクイックソートのソースでJava 7ソート「最適化」

、次のコメントは場所のカップル(例えばライン354)に表示されます。

/* 
    * Here and below we use "a[i] = b; i++;" instead 
    * of "a[i++] = b;" due to performance issue. 
    */ 

方法は、これがパフォーマンスの問題でしょうか?コンパイラはこれらを同じものに減らしませんか?

もっと広義には、これを自分自身で調べるための良い戦略は何ですか?ベンチマークを実行できますが、コンパイルされたコードの違いを分析することにもっと興味があります。しかし、私はどのツールを使うべきかわかりません。

+0

ホットスポットコンパイラが何か間違った(おそらく)か、マイクロベンチマークを書いた人がそれをねじ込んでいます...そして、私は後者を賭けました。 (いくつかのコードがメモリページや環境サイズなどのように他のコードより優れているように見える小さな理由はたくさんあります) – bestsss

+0

@bestsssもちろんこのコードを書いた人たちベンチマークの書き方結局のところ、Javaクィックソートの実装はベンチマークされ、細かく調整されています。 –

+1

FYI、このクラスの帰属する著者は、Josh Bloch、Jon Bentley(Programming Pearlsの著者)、Vladimir Yaroslavskiy –

答えて

7

これは一般的な質問に対する答えです。

バイトコードを見て、違いを理解することができます。私。 a[i] = b; i++;a[i++] = b;の両方を使って簡単な例を書くことができます。

バイトコードを表示する最も簡単な方法は、javapプログラムです(JDKに含める必要があります)。コードをjavac SomeFile.javaでコンパイルし、コードでjavap -c SomeFileを実行します(-cスイッチは、ファイル内の各メソッドのバイトコードを出力するようにjavapに指示します)。

eclipseを使用している場合は、this oneでも試すことができます。

+0

ありがとう - このプラグインは、生成されたバイトコードが同じでないことを示しています。今バイトコードを読む方法を読んでください! –

+9

私はバイトコードをどのように決定的に見ているのか分かりません。結局のところ、ほとんどの最適化はJITで行われます。私はさらに進んでいきます。この場合のバイトコードは完全に無関係です。この答えは誤解を招きます。 –

+1

HotSpotが行う多くの最適化のおかげで、バイトコードだけを見るだけでは、ジッタ後に期待されるパフォーマンスについての多くの手掛かりは得られません。 –

1

processor instructions generated by the hotspot engineが表示される方法があります。

+0

私はそのツールの名前を聞いて欲しいと思います。 – Voo

+0

@Voo、あまりにも、ホットスポットオプションです。 http://wikis.sun.com/display/HotSpotInternals/PrintAssemblyまだ、それをチェックする最良の方法はgdbを添付することです。 – bestsss

+0

@bestsss - ありがとう、それは私が探していたものです!私は今私の答えを更新しました。 –

5

私は2つの方法test1のTEST2を書き、コメントとしてコンパイルされたバイトコード(Snow Leopardの上のJava 1.6)の主要部分を追加します。

/* 
    *  14 iload_1 [b]  -> load value from address 1 to sack 
    *  15 iastore   -> store value from stack into int array 
    *  16 iinc 3 1 [i]  -> int increment value of address 3 
    *  19 iinc 3 1 [i]  -> int increment value of address 3 
    */ 
    public void test1() { 
     int b = 0; 
     int a[] = new int[10]; 
     for (int i=0; i<10; i++) { 
      a[i] = b; 
      i++; 
     } 
    } 

    /* 
    *  14 iinc 3 1 [i]  -> increment value of address 3 
    *  17 iload_1 [b]  -> load value from address 1 to stack 
    *  18 iastore   -> store value from stack into int array 
    *  19 iinc 3 1 [i]  -> increment value of address 3 
    */ 
    public void test2() { 
     int b = 0; 
     int a[] = new int[10]; 
     for (int i=0; i<10; i++) { 
      a[i++] = b; 
     } 
    } 

inc OPSの順序が異なります。しかし、両方のメソッドの演算合計は、test1test2は等しいです!したがって、バイトコードのパフォーマンスも同じにする必要があります。

+2

オプティマイザは、2つの連続したincコールを1つのadd $ reg、2コールに最適化することが考えられます(少なくともx86ではもっと速くなければなりません)。ホットスポット現在の最適化ではありませんか? – Voo