Le code Java est exécuté via une JVM. De ce fait, il peut difficilement rivaliser en vitesse d'exécution avec des langages compilés comme le C ou le C++. cela est la plupart de temps non bloquant dans le sens où les temps de traitement sont négligeables pour l'utilisateur. Néanmoins, il est nécessaire d'optimiser son code pour trois raisons principales:
Consommer moins de CPU pour obtenir des applications plus fluides.
Consommer moins de mémoire pour de pas tomber dans la zone de pagination mémoire ou être trop gourmand vis à vis des autres applications tournant sur la machine.
Obtenir des temps de réponse acceptables dans le cas de traitements importants ou critiques.
Les conseils suivants vous permettront de facilement augmenter la vitesse d'exécution de votre application et de diviser d'autant la mémoire consommée.
Il faut utiliser au maximum les variables primitives qui ne sont pas des objets et donc sont très légers en mémoire.
Rappel de la taille des primitifs en Java:
Type |
Taille ( bits ) |
long |
64bits |
int |
32bits |
boolean |
8bits (faux 1 bit) |
byte |
8 bits |
float |
32 bits |
double |
64 bits |
Remarquons qu'il n'est pas plus avantageux de travailler avec un boolean qu'avec un byte.
Les opérations sur les primitifs sont très rapidement exécutées car facilement traduisibles en code machine du processeur local.
A l'opposé, les objets Java possèdent une encapsulation (environ 50 octets pour un objet Integer par exemple ). Il sont donc gourmands en mémoire.
L'instanciation d'un objet ( new
) étant une opérations très coûteuse
en temps CPU, ne surtout pas re-instancier des objets mais modifier
au maximum les objets existants ( valable pour les objets graphiques
).
Toute copie d'un tableau vers un autre lorsque le nombre d'éléments est important doit être effectuée via la méthode System.arraycopy() . Voir l'exemple explicite suivant. Le temps de copie est divisé par 2.5.
byte[]bTest=new
byte[10000000];
byte[]bTest2=new
byte[10000000];
for(i=0;i<10000000;i++){
bTest2[i]=bTest[i];
}
250ms
System.arraycopy(bTest,0,bTest2,0,10000000);
110ms
Il faut créer des tableaux aux dimensions les plus petites possibles. En effet une affectation dans un tableau à deux dimension:
byte[][] bTest;
bTest[0][0]=10;
prend presque deux fois plus de temps que:
byte[] bTest;
bTest[0]=10;
Et ainsi de suite en augmentant le nombre de dimensions du tableau.
Les try / catch sur les exceptions sont assez coûteux, préférer capturer des exceptions plus générales comme Exception et cela sur de larges zones de code.( Sauf s'il y a des raisons valables de capturer des exceptions plus fines ).
Par exemple, préférer:
try{
a();
b();
}
catch(Exception
e){
}
à
try{
a();
}
catch(Exception
e){
}
try{
b();
}
catch(Exception
e){
}
Les constantes ( static final ) sont plus rapides à manipuler. De même, utiliser les méthodes final accélère légèrement le chargement des classes.
Les caractères ( primitifs char ou objets String ) sont toujours codés en mémoire en format Unicode, soit sur 2 octets au lieu d'un seul en ASCII. Par conséquent, une chaîne peut prendre davantage de mémoire que prévu... En revanche, Java est alors compatible avec les caractères de la grande majorité des langages ( chinois, indien, japonais...).