So i've made the following benchmark to try and understand how Lambas impact performance.
@Fork(1)
@Measurement(iterations = 5)
@Warmup(iterations = 5)
public class LambdaBenchmark {
@State(Scope.Thread)
public static class MyInteger {
public Integer value = 10;
}
@Benchmark
public void TestValueInside(MyInteger integer) {
Function<Integer, Integer> toTest = i -> i + 10;
toTest.apply(1);
}
@Benchmark
public void TestValueOutside(MyInteger integer) {
Function<Integer, Integer> toTest = i -> i + integer.value;
toTest.apply(1);
}
@Benchmark
public void TestValueOutsideFinal(MyInteger integer) {
int i2 = 10;
Function<Integer, Integer> toTest = i -> i + i2;
toTest.apply(1);
}
@Benchmark
public void TestValueOutsideLocalCopy(MyInteger integer) {
int i2 = integer.value;
Function<Integer, Integer> toTest = i -> i + i2;
toTest.apply(1);
}
}
I'm kinda puzzled by the results:
Benchmark Mode Cnt Score Error Units
LambdaBenchmark.TestValueInside thrpt 5 1494683335,686 ▒ 157769032,327 ops/s
LambdaBenchmark.TestValueOutside thrpt 5 755197977,631 ▒ 39587849,696 ops/s
LambdaBenchmark.TestValueOutsideFinal thrpt 5 3007751583,191 ▒ 178696557,885 ops/s
LambdaBenchmark.TestValueOutsideLocalCopy thrpt 5 771307179,267 ▒ 13613431,113 ops/s
Why is TestValueOutsideFinal
so much faster than TestValueInside
? We're using an external variable that may be considered final but it's still a variable rather than a direct value ? Or is the value 10
constantly being recreated rather than always using the same addressed variable ?
EDIT:
After taking into account what @AlBlue said, it's indeed showing much closer results.
Here are the results once I return each value:
Benchmark Mode Cnt Score Error Units
LambdaBenchmark.TestValueInside thrpt 5 309129197,389 ▒ 32089680,994 ops/s
LambdaBenchmark.TestValueOutside thrpt 5 283435336,319 ▒ 52230809,938 ops/s
LambdaBenchmark.TestValueOutsideFinal thrpt 5 360590518,854 ▒ 3072257,599 ops/s
LambdaBenchmark.TestValueOutsideLocalCopy thrpt 5 279159794,477 ▒ 12871790,409 ops/s
Your code is falling for the oldest problem in benchmarking: you are ignoring the results of the methods. As a result everything is being thrown away and you're measuring random data.
Always, always, always return the value from the function call, or have it consumed with Blackhole.consume
. Otherwise you won't get what you expect you are measuring.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments