LoginSignup
16
13

More than 5 years have passed since last update.

Javaでfinalを付けると遅い?

Posted at

随分昔の記事を取り出して恐縮ですが、finalをつけたらパフォーマンスが落ちたでござるの巻 という話がありました。

この違いがなぜ起こるか調べてみました。

public static void main(String[] args) {
    final int NUM = 31;
    long start = System.currentTimeMillis();
    for (int i = 0; i < Integer.MAX_VALUE; i++) {
        int hash = 17;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
    }
    System.out.println(System.currentTimeMillis() - start);
}

この場合、javapの結果を眺めてみると、違いはが出てくるのは、finalを付けるとスタックに積むのがbipush命令になり、finalを付けないとiload_1命令になるという点だけです。

これをWindowsで実行すると…

finalあり:3244
finalなし:2527

確かにfinalなしの方が速い結果が得られます。

しかしこのコードよく見ると、hashがループの外で使われていないので、最適化のやり方次第で大きく差がでてしまいます。-XintをつけてJITを効かせずに実行してみます。

finalあり:57513
finalなし:57441

変わりません。つまりbipushとiload_1で速度差は無いということです。

さて比較をフェアにするために、hashをループの外で使うようにして、-serverオプションをつけて最適化して実行してみます。

コードは以下のとおり。

public static void main(String[] args) {
    final int NUM = 31;
    long start = System.currentTimeMillis();
    int hash = 17;
    for (int i = 0; i < Integer.MAX_VALUE; i++) {
        hash = hash * NUM + i;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
        hash = hash * NUM + i;
    }
    System.out.println(hash +":"+ (System.currentTimeMillis() - start));
}

結果は…

finalあり:9021
finalなし:12478

となり、「finalを付けた方が、最適化されやすい」という通説どおりの結果になります。

16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13