以下代码:
public void execute(Object[] arguments)
{
for(MyListener listener : listOfListeners)
{
listener.apply(((Double) arguments[0]).longValue());
}
}
是否会为所有侦听器调用longValue(),还是JVM会对此进行优化并且只计算一次?换句话说:以上是否慢于此:
public void execute(Object[] arguments)
{
long id = ((Double) arguments[0]).longValue()
for(MyListener listener : listOfListeners)
{
listener.apply(id);
}
}
答案 0 :(得分:2)
是的,此优化称为loop invariant hoisting,HotSpot JVM绝对称为can do this。
我们可以使用简单的JMH基准来验证这一点。
package bench;
import org.openjdk.jmh.annotations.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@State(Scope.Benchmark)
public class Listeners {
List<Listener> listOfListeners = IntStream.range(0, 50)
.mapToObj(Listener::new)
.collect(Collectors.toList());
Object[] arguments = {Math.random()};
@Benchmark
public void inside() {
for (Listener listener : listOfListeners) {
listener.apply(((Double) arguments[0]).longValue());
}
}
@Benchmark
public void outside() {
long id = ((Double) arguments[0]).longValue();
for (Listener listener : listOfListeners) {
listener.apply(id);
}
}
static class Listener {
private long sum;
Listener(int initialValue) {
this.sum = initialValue;
}
public void apply(long id) {
sum += id;
}
}
}
结果显示,inside
和outside
方法在性能方面均相同。
Benchmark Mode Cnt Score Error Units
Listeners.inside avgt 10 53,354 ± 0,317 ns/op
Listeners.outside avgt 10 53,690 ± 0,373 ns/op