每次在多个侦听器中传递时计算的参数

时间:2016-08-15 18:12:17

标签: java performance jvm

以下代码:

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);
  }
}

1 个答案:

答案 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;
        }
    }
}

结果显示,insideoutside方法在性能方面均相同。

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