J'ai vu beaucoup de fils de discussion ici qui comparent et essaient de répondre à la question de savoir lequel est le plus rapide : newInstance
o new operator
.
En regardant le code source, il semblerait que newInstance
devrait être beaucoup plus lent Je veux dire qu'il fait tellement de contrôles de sécurité et utilise la réflexion. Et j'ai décidé de mesurer, d'abord en utilisant jdk-8. Voici le code utilisant 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 {
}
}
Je ne pense pas qu'il y ait de grandes surprises ici (le JIT fait beaucoup d'optimisations qui font que cette différence n'est pas ). si grand ):
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
La différence pour le code chaud serait d'environ 2x et bien pire pour le temps de tir unique.
Maintenant je passe à jdk-9 (build 157 au cas où cela aurait de l'importance) et j'exécute le même code. Et les résultats :
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
C'est un coqueluche 50x différence dans le code chaud. J'utilise la dernière version de jmh (1.19.SNAPSHOT).
Après avoir ajouté une méthode supplémentaire au test :
@Fork(1)
@Benchmark
public Something newInstanceJDK9() throws Exception {
return Something.class.getDeclaredConstructor().newInstance();
}
Voici les résultats globaux 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
Quelqu'un peut-il m'éclairer sur pourquoi il y a une si grande différence ?