Ai-je tort de penser qu'il devrait être plus rapide et plus efficace ? Je n'aimerais pas avoir à tout modifier dans un gros programme pour m'apercevoir que j'ai perdu mon temps.
Réponse courte
Oui, vous avez tort. Dans la plupart des cas, cela fait petite différence en termes d'espace utilisé.
Il est ne vaut pas la peine d'essayer d'optimiser ceci ... à moins que vous n'ayez des preuves claires qu'une optimisation est nécessaire. Et si vous le faites besoin de pour optimiser l'utilisation de la mémoire des champs d'objets en particulier, vous devrez probablement prendre d'autres mesures (plus efficaces).
Réponse plus longue
La machine virtuelle Java modélise les piles et les champs d'objets en utilisant des décalages qui sont (en fait) des multiples de la taille d'une cellule primitive de 32 bits. Ainsi, lorsque vous déclarez une variable locale ou un champ d'objet en tant que (disons) un byte
la variable/le champ sera stocké(e) dans une cellule de 32 bits, tout comme un fichier int
.
Il y a deux exceptions à cette règle :
-
long
y double
les valeurs nécessitent 2 cellules primitives de 32 bits
- Les tableaux de types primitifs sont représentés sous forme compacte, de sorte que (par exemple) un tableau d'octets contient 4 octets par mot de 32 bits.
Donc, il pourrait il vaut la peine d'optimiser l'utilisation de long
y double
... et de grands tableaux de primitives. Mais en général non.
En théorie, un système JAT pourrait être capable d'optimiser cela, mais en pratique je n'ai jamais entendu parler d'un JIT qui le fasse. L'un des obstacles est que le JIT ne peut généralement pas s'exécuter avant que toutes les instances de la classe à compiler aient été créées. Si le JIT optimisait la disposition de la mémoire, vous pourriez avoir deux (ou plus) "saveurs" d'objet de la même classe ... et cela présenterait d'énormes difficultés.
Revisitation
En examinant les résultats du benchmark dans la réponse de @meriton, il apparaît que l'utilisation de la fonction short
y byte
au lieu de int
subit une pénalité de performance pour la multiplication. En effet, si vous considérez les opérations de manière isolée, la pénalité est significative. (Vous ne devriez pas les considérer isolément... mais c'est un autre sujet).
Je pense que l'explication est que le JIT effectue probablement les multiplications en utilisant des instructions de multiplication de 32 bits dans chaque cas. Mais dans le byte
y short
Dans ce cas, il exécute extra des instructions pour convertir la valeur intermédiaire de 32 bits en un byte
o short
à chaque itération de la boucle. (En théorie, cette conversion pourrait être effectuée une fois à la fin de la boucle ... mais je doute que l'optimiseur soit capable de comprendre cela).
Quoi qu'il en soit, cela met en évidence un autre problème lié au passage à l'euro. short
y byte
comme une optimisation. Cela pourrait améliorer les performances pire ... dans un algorithme qui est arithmétiquement et informatiquement intensif.
Questions secondaires
Je sais que Java n'a pas de types non signés mais y a-t-il quelque chose d'autre que je puisse faire si je sais que le nombre ne sera que positif ?
Non. Pas en termes de performances en tout cas. (Il existe certaines méthodes dans Integer
, Long
etc. pour traiter int
, long
etc. comme non signés. Mais cela ne donne aucun avantage en termes de performances. Ce n'est pas leur but).
(Je suppose que le ramasseur d'ordures ne traite que les objets et non les primitives, mais il supprime quand même toutes les primitives des objets abandonnés, n'est-ce pas ? )
Correct. Un champ d'un objet est partie de l'objet. Il disparaît lorsque l'objet est mis au rebut. De même, les cellules d'un tableau disparaissent lorsque le tableau est collecté. Lorsque le type de champ ou de cellule est un type primitif, la valeur est stockée dans le champ/cellule ... qui fait partie de l'objet/du tableau ... et qui a été supprimé.