私たちはレイテンシーの影響を受けやすいアプリケーションに取り組んでおり、あらゆる種類のメソッドを ( jmhを使用して) マイクロベンチマークしています。ルックアップ メソッドをマイクロベンチマークし、結果に満足した後、最終バージョンを実装しましたが、最終バージョンはベンチマークしたばかりの 3 倍遅いことがわかりました。
enum
原因は、実装されたメソッドがではなくオブジェクトを返していたことint
です。以下は、ベンチマーク コードの簡略化されたバージョンです。
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
public class ReturnEnumObjectVersusPrimitiveBenchmark {
enum Category {
CATEGORY1,
CATEGORY2,
}
@Param( {"3", "2", "1" })
String value;
int param;
@Setup
public void setUp() {
param = Integer.parseInt(value);
}
@Benchmark
public int benchmarkReturnOrdinal() {
if (param < 2) {
return Category.CATEGORY1.ordinal();
}
return Category.CATEGORY2.ordinal();
}
@Benchmark
public Category benchmarkReturnReference() {
if (param < 2) {
return Category.CATEGORY1;
}
return Category.CATEGORY2;
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder().include(ReturnEnumObjectVersusPrimitiveBenchmark.class.getName()).warmupIterations(5)
.measurementIterations(4).forks(1).build();
new Runner(opt).run();
}
}
上記のベンチマーク結果:
# VM invoker: C:\Program Files\Java\jdk1.7.0_40\jre\bin\java.exe
# VM options: -Dfile.encoding=UTF-8
Benchmark (value) Mode Samples Score Error Units
benchmarkReturnOrdinal 3 thrpt 4 1059.898 ± 71.749 ops/us
benchmarkReturnOrdinal 2 thrpt 4 1051.122 ± 61.238 ops/us
benchmarkReturnOrdinal 1 thrpt 4 1064.067 ± 90.057 ops/us
benchmarkReturnReference 3 thrpt 4 353.197 ± 25.946 ops/us
benchmarkReturnReference 2 thrpt 4 350.902 ± 19.487 ops/us
benchmarkReturnReference 1 thrpt 4 339.578 ± 144.093 ops/us
関数の戻り値の型を変更するだけで、パフォーマンスがほぼ 3 倍向上しました。
列挙型オブジェクトと整数を返すことの唯一の違いは、一方が 64 ビット値 (参照) を返し、もう一方が 32 ビット値を返すことだと思いました。私の同僚の 1 人は、潜在的な GC の参照を追跡する必要があるため、enum を返すと追加のオーバーヘッドが追加されると推測していました。(しかし、enum オブジェクトが静的な最終参照であることを考えると、そうする必要があるのは奇妙に思えます)。
パフォーマンスの違いの説明は何ですか?
アップデート
誰でもクローンを作成してベンチマークを実行できるように、ここで Maven プロジェクトを共有しました。誰かが時間/興味を持っている場合は、他の人が同じ結果を再現できるかどうかを確認するのに役立ちます. (私は Windows 64 と Linux 64 の 2 つの異なるマシンでレプリケートしました。どちらも Oracle Java 1.7 JVM のフレーバーを使用しています)。@ZhekaKozlov は、メソッド間に違いは見られなかったと述べています。
実行するには: (リポジトリのクローン作成後)
mvn clean install
java -jar .\target\microbenchmarks.jar function.ReturnEnumObjectVersusPrimitiveBenchmark -i 5 -wi 5 -f 1