Questions sur l'optimisation

Driix Messages postés 8 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 4 mars 2008 - 3 mars 2008 à 20:21
Driix Messages postés 8 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 4 mars 2008 - 4 mars 2008 à 18:44
Bonjour,

Je me pose des questions sur l'optimisation (rapidité, utilisation mémoire,...).

1)
On m'a dit qu'il était préférable de déclarer les primitives, lorsque celles-ci sont utilisées plusieurs fois, de cette façon :

private static final int NB = 0;

Pensez-vous que c'est une source d'optimisation ? Pourquoi ?

2)
Une question sur les boucles.

cas 1 :

for (int i = 0; i < 10000000; i++) {
    String toto = getToto(i);
    ...
}

cas 2 :


String toto = null;


for (int i = 0; i <
10000000
; i++) {

    toto = getToto(i);

    ...

}




Dans le cas 2, la variable toto existe encore après la boucle.
Mais dans le cas 1, une nouvelle variable toto est créée à chaque itération.

Quelle est la meilleure solution ? Pourquoi ?

Si vous avez des conseils à me donner sur l'optimisation, je suis preneur.

Merci d'avance.

4 réponses

cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
3 mars 2008 à 21:40
Salut,

Tout dépend de la machine virtuelle : si elle est bien faite ou non (et oui, il n'y a pas que la jvm de sun dans la vie :p).

Disons qu'en toute logique :
1) déclarer une "variable" en tant que static déjà est source d'optimisation : elle est partagée entre toutes les instances de classe, elle est crée dès le lancement de l'application, et il n'en existera qu'une seule instance tout le long de l'utilisation du programme => efficacité mémoire, et efficacité CPU (pas besoin de créer une nouvelle instance de la variable à chaque création d'instance d'objet).
De plus, la déclarer final implique qu'elle soit constante. Du coup, sa valeur ne change pas, et le compilo doit (je dis bien dois, et non pas fait !) remplacer tout les appels à cette constantes par sa valeur directement => optimisation là aussi de mémoire (pas la peine de créer de variable, puisqu'elle n'a pas besoin d'être stockée) et CPU (pas de lecture d'adresse mémoire puisqu'elle n'existe pas...).

Il s'agit donc d'une source d'optimisation très simple à mettre en oeuvre (c'est pas pour rien que c'est utilisé dans beaucoup de sources ici).

2) Là encore, si le compilo n'est pas bête, les deux façon se vale : il "doit" faire la même chose dans les deux cas, sauf si tu utilise la variable hors de la boucle for.
Cependant, je pense que la première solution est la solution la plus sûre niveau perf : au moins t'es sûr qu'il n'alloue pas l'espace mémoire d'un String à chaque tour de boucle !

Idem pour le i++ : mes profs me disaient que le ++i était plus rapide en C++ (je sais pas si c'est aussi valable en java avec la jvm de sun vu que c'est interprêté dynamiquement, mais pour des compilations en natif, ca doit l'être certainement !).
______________________________________
DarK Sidious
0
Driix Messages postés 8 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 4 mars 2008
3 mars 2008 à 22:47
Merci pour ta réponse.

Un petit exemple pour ma première question :



cas 1 :





private static final int INT_DEUX = 2;


for (...) {
    ...
    String toto = tata.substring(
INT_DEUX
);
    ...
}

cas 2 :


for (...) {

    ...

    String toto = tata.substring(
2
);

    ...

}

Le cas 1 est mieux que le cas 2 ? En faisant

"tata.substring(
2


)" le "2" créé une variable en mémoire ?



Tu dis :



Du coup, sa valeur ne change pas, et le compilo doit (je dis bien
dois, et non pas fait !) remplacer tout les appels à cette constantes
par sa valeur directement => optimisation là aussi de mémoire (pas
la peine de créer de variable, puisqu'elle n'a pas besoin d'être
stockée) et CPU (pas de lecture d'adresse mémoire puisqu'elle n'existe
pas...).





Si je mets une ArrayList en constante, je peux ajouter des objets à cette liste.
Je ne comprends pas comment elle peut exister si elle n'est pas stockée, et comment y accéder s'il n'y a pas de lecture d'adresse mémoire.

Pourrais-tu m'expliquer stp.











Pour ma deuxième question.

Tu dis :



Cependant, je pense que la première solution est la solution la
plus sûre niveau perf : au moins t'es sûr qu'il n'alloue pas l'espace
mémoire d'un String à chaque tour de boucle !




J'aurais plutôt pensé au cas 2, puisque dans le cas 1 on recréer un nouveau "String toto" alors que dans le 2 on réutilise la même variable. Pourrais-tu m'expliquer stp.

Désolé pour toutes ces questions
0
cs_DARKSIDIOUS Messages postés 15814 Date d'inscription jeudi 8 août 2002 Statut Membre Dernière intervention 4 mars 2013 130
4 mars 2008 à 07:08
Salut,

les constantes sont... constantes, donc ca ne sers à rien de faire un tableau "constant" qui a pour but de changer : java te le permettra pas !

Ce que je voulais dire, c'est que faire :
final int index = 2;
String toto = getToto(index);

et :
String toto = getToto(2);

devrait en théorie donner les même performances : le compilo est censé remplacé le index par 2 lors de la compilation, cependant, du point de vue maintenabilité et lisibilité, il vaut bien mieux utilisé la première solution ! Mais ne t'attends pas à doubler les performances de ton programme en utilisant des constantes à la place de variables !

Pour un arrayList contant, une fois qu'il sera initialisé, tu ne pourras plus le modifier ! C'est le but du mot clé "final" !

Pour le deuxième point, t'as raison, j'ai inversé les deux, c'est le deuxième cas qui risque d'être plus rapide.
______________________________________
DarK Sidious
0
Driix Messages postés 8 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 4 mars 2008
4 mars 2008 à 18:44
Tu dis :





"les constantes sont... constantes, donc ca ne sers à rien de
faire un tableau "constant" qui a pour but de changer : java te le
permettra pas !"
"


Pour un arrayList contant, une fois qu'il sera initialisé, tu ne pourras plus le modifier ! C'est le but du mot clé "final" !"






Le mot clé "final" permet d'indiquer au compilateur que "l'association" ne peut être changée (le code produit est donc plus optimisé).
Cela ne veut pas dire que la valeur elle-même est constante.



Exemple :



private static final ArrayList LISTE_TOTO = new ArrayList();

private void addToto(String valToto) {
   
LISTE_TOTO
.add(valToto);
}

Merci pour tes réponses.
Malheureusement ça ne répond pas exactement à mes interrogations...

J'aurais besoin d'un expert, car je pense que mes questions sont <strike>tordus</strike> subtiles.

Pour résumer :

Pourquoi mettre une primitive en "static final" optimise ? (Gestion des primitives en mémoire)
Comment sont gérés les variables dans les boucles ?
(Gestion
en mémoire
des variables dans les boucles)







Merci d'avance.
0
Rejoignez-nous