Здесь я видел много потоков, которые сравнивают и пытаются ответить быстрее: newInstance
или new operator
.
Посмотрев на исходный код, кажется, что newInstance
должен быть намного медленнее, я имею в виду, что он делает так много проверок безопасности и использует отражение. И я решил измерить, сначала запустив jdk-8. Вот код с помощью jmh
.
@BenchmarkMode(value = { Mode.AverageTime, Mode.SingleShotTime })
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@State(Scope.Benchmark)
public class TestNewObject {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder().include(TestNewObject.class.getSimpleName()).build();
new Runner(opt).run();
}
@Fork(1)
@Benchmark
public Something newOperator() {
return new Something();
}
@SuppressWarnings("deprecation")
@Fork(1)
@Benchmark
public Something newInstance() throws InstantiationException, IllegalAccessException {
return Something.class.newInstance();
}
static class Something {
}
}
Я не думаю, что здесь есть большие сюрпризы (JIT делает много оптимизаций, которые делают эту разницу не такой большой):
Benchmark Mode Cnt Score Error Units
TestNewObject.newInstance avgt 5 7.762 ± 0.745 ns/op
TestNewObject.newOperator avgt 5 4.714 ± 1.480 ns/op
TestNewObject.newInstance ss 5 10666.200 ± 4261.855 ns/op
TestNewObject.newOperator ss 5 1522.800 ± 2558.524 ns/op
Разница для горячего кода будет примерно 2x и намного хуже для одиночного времени.
Теперь я переключаюсь на jdk-9 (строят 157 в случае, если это имеет значение) и запускает тот же код. И результаты:
Benchmark Mode Cnt Score Error Units
TestNewObject.newInstance avgt 5 314.307 ± 55.054 ns/op
TestNewObject.newOperator avgt 5 4.602 ± 1.084 ns/op
TestNewObject.newInstance ss 5 10798.400 ± 5090.458 ns/op
TestNewObject.newOperator ss 5 3269.800 ± 4545.827 ns/op
Это whooping 50x разница в горячем коде. Я использую последнюю версию jmh (1.19.SNAPSHOT).
После добавления еще одного метода к тесту:
@Fork(1)
@Benchmark
public Something newInstanceJDK9() throws Exception {
return Something.class.getDeclaredConstructor().newInstance();
}
Ниже приведены общие результаты n jdk-9:
TestNewObject.newInstance avgt 5 308.342 ± 107.563 ns/op
TestNewObject.newInstanceJDK9 avgt 5 50.659 ± 7.964 ns/op
TestNewObject.newOperator avgt 5 4.554 ± 0.616 ns/op
Может кто-то пролить свет на то, почему существует такая большая разница?