ここでは、Javaコンパイルの最適化に関する簡単な質問があります。コンパイル時のJava定数式関連コードの最適化
は、パフォーマンスの面でコードをコンパイルするか、一般的に
final int CONSTANT_NUMBER=7;
に等しい
final int CONSTANT_NUMBER="Foo Bar".length();
ですか?
ここでは、Javaコンパイルの最適化に関する簡単な質問があります。コンパイル時のJava定数式関連コードの最適化
は、パフォーマンスの面でコードをコンパイルするか、一般的に
final int CONSTANT_NUMBER=7;
に等しい
final int CONSTANT_NUMBER="Foo Bar".length();
ですか?
いいえJavaコンパイラはコンパイル時に"Foo Bar".length()
を評価しません。
が.length()
コールが保たれていることを、あなたが見ることができるコンパイル.class
ファイルにjavap -v
を使用して、これらのクラス
public class ConstantCheck {
final int CONSTANT_NUMBER = "Foo Bar".length();
}
と
public class ConstantCheck {
final int CONSTANT_NUMBER = 7;
}
考えてみましょう:
で旧結果を
...
final int CONSTANT_NUMBER;
descriptor: I
flags: ACC_FINAL
public text.ConstantCheck();
descriptor:()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String Foo Bar
7: invokevirtual #3 // Method java/lang/String.length:()I
10: putfield #4 // Field CONSTANT_NUMBER:I
13: return
...
後者の最初のケースで
...
final int CONSTANT_NUMBER;
descriptor: I
flags: ACC_FINAL
ConstantValue: int 7
public text.ConstantCheck();
descriptor:()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 7
7: putfield #2 // Field CONSTANT_NUMBER:I
10: return
....
に.length
コールは、それが
5: bipush 7
7: putfield #2 // Field CONSTANT_NUMBER:I
ええ、それを見るのは残念です。私はコンパイラがそのようなコードを検出できると思った。 – LapisSea
コンパイルからは、最初はメソッド呼び出しがあるので、2番目のメソッドは少し高速になります。しかし、今日のマシンは、これが目立つかまたは重要であるほど早すぎます。
性能について - 現代のコンパイラは "Foo Bar"が定数であり、式をlengthに置き換える必要があることを知るためにはスマートでなければなりません。しかし、変数を変数に変更した場合は、毎回メソッドを呼び出すようにコンパイラをだますことができます。大きなループで実行すると、最初に少し速くなります。
私は大きなループで実行させることでこれをテストし、2番目の方法ではパフォーマンスがやや向上しました。私のコンパイラはメソッド呼び出しを定数で置き換えるほどスマートではないと思います。
私のマシン上でのメソッド呼び出しよりもパフォーマンスが良い、直接的なint型のほうが優れていますが、別のコンパイラでは異なることがあります。
ありがとう!それはまさに私が探していたものです! :D – LapisSea
フィールドに書き込まれるだけ定数の第二の場合に
存在しますコードのコンパイルとパフォーマンスが同じではありません。 – Blobonat
もちろん、他のものに強く影響するものがあります。 – LapisSea