L'autoboxing contre manuel de boxe en Java
Pourquoi est le deuxième morceau de code plus rapide?
Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
for (double j = 0.0; j < 10000; j++) {
map.put(i, j);
}
}
Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
for (double j = 0.0; j < 10000; j++) {
map.put(new Integer(i), new Double(j));
}
}
- Essayez d'envelopper les deux parties autour de et microbenchmark de nouveau.
- parce qu'à l'extérieur de votre artificiel micro-benchmark qui est incorrect, il n'a pas d'importance puisque ce sera optimisé loin mais JIT, éventuellement, dans le monde réel.
Vous devez vous connecter pour publier un commentaire.
L'autoboxing utilise
Integer.valueOf
, qui en interne caches Entier des objets pour les petits entiers (par défaut -128 à 127, mais la valeur maximale peut être configuré avec le "java.lang.Entier.IntegerCache.haut de la propriété" - voir le code source d'un nombre Entier.valueOf), de sorte qu'il est différent de l'appel denew Integer
directement. Parce queInteger.valueOf
fait une vérification rapide de l'ampleur de la valeur de l'entier avant d'appelernew Integer
, c'est un peu plus rapide pour appelernew Integer
directement (mais il utilise plus de mémoire si vous avez beaucoup de petits nombres). Répartition en Java est très rapide, et le temps à faire des GC est proportionnelle au nombre de courte durée de vie des objets (c'est à dire pas proportionnelle à la quantité de déchets), de sorte que GC est également très rapide.Mais selon la version de la JVM et les optimisations sont activés, il est le scalaire de rechange optimisation, ce qui peut produire une grande différence de performances lors de l'affectation de courte durée de vie des objets (dans votre exemple que l'optimisation ne peut pas être fait, parce que vous stockez des objets de la carte, mais dans beaucoup d'autres situations, il est utile).
Dans les dernières versions de la JVM, il est scalaire de remplacement optimisation (sauf dans 1.6.0_18 où l'évasion de l'analyse est temporairement désactivé), ce qui signifie que les affectations de courte durée de vie des objets peut être optimisé à l'écart. Lorsque scalaire de remplacement dans la JVM qui était nouveau, quelqu'un a fait une référence où il y avait un code similaire à la vôtre. Le résultat est que le code qui a utilisé des primitives a été le plus rapide, le code explicite
new Integer()
appels a été presque aussi vite que celle que l'utilisation de primitives, et le code qui a utilisé l'autoboxing a été beaucoup plus lent. C'est parce que l'autoboxing utiliseInteger.valueOf
et au moins en arrière puis scalaire de remplacement d'optimisation ne prendre que le cas spécial en considération. Je ne sais pas si l'optimisation a été améliorée depuis.L'autoboxing utilisera
Integer.valueOf
etDouble.valueOf
. Il y a une surcharge, à l'appel de ces méthodes (bien qu'il finira par être incorporé). AussiInteger.valueOf
fait quelques vérifications pour les faibles valeurs d'usage commun instances, ce qui n'est pas souvent une victoire dans votre code (bien qu'il pourrait réduire la taille de segment de mémoire un peu). Commun des instances peut être une victoire où ils réduisent la taille de segment de mémoire, GC temps et pourrait même améliorer l'égalité de test de performance..Mais, en général, c'est un microoptimisation qui vous convient, en général, de l'ignorer.
Parce que les résultats de microbenchmarks ne sont pas fiables?
Aussi, l'auto-boxing est effectué à l'aide d'Entiers.valueOf() et Double.valueOf(), pas les constructeurs.