IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

for(int i = 0, I = set.size(); i < I; i++) plus rapide?


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de muad'dib
    Homme Profil pro
    Développeur Java
    Inscrit en
    Janvier 2003
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2003
    Messages : 1 013
    Par défaut for(int i = 0, I = set.size(); i < I; i++) plus rapide?
    Bonjour à tous,

    Voilà j'ai vu ça dans le code de ma boite et je me demandais si cela représentait réellement un gain de performances :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Set<Long> s = new HashSet<Long>();
     
    for(i = 0, I = s.size(); i < I; i++) {
    ...
    }
    J'ai donc fait un petit code de test et les résultats s'avèrent plutôt aléatoires :
    s.size() = 3719 ms

    I = 4187 ms
    Le résultat ne donne pas vraiment l'avantage à l'une ou l'autre méthode. Cela dit ma machine est assez instable et rame, donc j'aurais voulu savoir si l'un d'entre vous connaissait le mécanisme de Java concernant cet aspect particulier des boucles?
    Mon sentiment est que la machine virtuelle stocke dans sa mémoire la variable s.size() afin de n'avoir à appeler la fonction qu'une seule fois.

    Je vous colle le code du jeu de test que j'ai utilisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public static void main(String[] args) throws IOException {
    	Set<Long> s = new HashSet<Long>();
    	long l = 0;
    	long i, I = 0;
    	final int OCCURS = 50;
     
    	for(i = 0; i < 999999; i++) {
    		s.add(i);
    	}
     
    	l = System.currentTimeMillis();
     
    	for(int j = 0; j < OCCURS; j++) {
    		for(i = 0; i < s.size(); i++) {
    			if(i % 400000 == 0)
    				System.out.print(i + " ");
    		}
    	}
    	System.out.print("\n");
    	l = System.currentTimeMillis() - l;
    	System.out.println("s.size() = " + l + " ms");
     
    	l = System.currentTimeMillis();
     
    	for(int j = 0; j < OCCURS; j++) {
    		for(i = 0, I = s.size(); i < I; i++) {
    			if(i % 10000 == 0)
    				System.out.print(i + " ");
    		}
    	}
    	System.out.print("\n");
    	l = System.currentTimeMillis() - l;
    	System.out.println("I = " + l + " ms");
     
    }
    Merci d'avance d'éclairer ma lanterne

  2. #2
    Membre éclairé
    Homme Profil pro
    NoOb
    Inscrit en
    Mai 2007
    Messages
    554
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : NoOb

    Informations forums :
    Inscription : Mai 2007
    Messages : 554
    Par défaut
    Bonjour,

    Je sais pas si c'est plus rapide, mais il me semble que c'est plus optimal, on appel seulement une fois la méthode size(), au lieu de l'appeler à chaque tour de la boucle. Donc au final, c'est probablement plus rapide.

  3. #3
    Membre Expert
    Avatar de muad'dib
    Homme Profil pro
    Développeur Java
    Inscrit en
    Janvier 2003
    Messages
    1 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2003
    Messages : 1 013
    Par défaut
    Il est vrai qu'en langage C il peut être très avantageux d'appliquer cette pratique. Mais justement, au même effet que le garbage collector, le langage Java ayant tendance à faciliter grandement la tache du programmeur, je me demandais si cette manipulation n'était pas automatisée par la machine virtuelle?

  4. #4
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Attention, ces codes ne sont pas strictement équivalents:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(i = 0, I = s.size(); i < I; i++) {
        // code
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(i = 0; i < s.size(); i++) {
        // code
    }
    s.size() peut très bien renvoyer une valeur différente à chaque itération.

    Il faut faire attention lorsque l'on cherche à optimiser, à ne pas introduire d'erreur.

    J'aurais envie de dire qu'il suffit d'écrire sa boucle intelligemment pour qu'il ne soit pas nécessaire de se poser la question de l'optimisation.

    Si 's' est un Iterable (Collection, List, ...), autant faire une boucle for étendue ou bien utiliser explicitement un itérateur.

    Si la boucle est sur un tableau, on pourra utiliser une boucle étendue on une boucle classique sur tab.length. On ne doit rien y gagner à mettre la longueur dans une variable locale.

    Ces deux cas regroupent à mon avis la plupart des parcours.

    Pour les autres, si la limite de la boucle est fixe, connue à l'avance et nécessite l'appel à une méthode, autant la mettre dans une variable locale, en effet.

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Quant aux raisons pour laquelle ça n'a pas l'air de prendre plus de temps d'une manière ou d'une autre, on peut supposer que :

    - Vu que HashMap.size() ne fait que renvoyer une variable, on ne paie que l'appel de méthode, ce qui, pour un nombre de fois raisonnable, n'est finalement pas grand-chose.
    - La JVM pourrait très bien s'être rendue compte que HashMap.size() peut être optimisé en inline dans ce cas-là, ce qui ne fait plus beaucoup de différence avec la variable locale.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Un gros +1 avec ce qui a été dit par Deaf et thelvin.

    Je rajouterais juste que je trouve particulièrement hideux les déclarations de variables en début de méthode ! Surtout pour des variables temporaires de boucle. On n'est pas en C...

    En plus il y a une erreur de type (long alors que les index sont des int).


    Je finirais juste par confirmer que le for étendu/les Iterators sont les meilleurs moyens de parcourir une collection. Les accès par index peuvent donner des résultats plus ou moins différents selon l'implémentation de la collection.


    a++

  7. #7
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    La FAQ répond à cela:
    pour les Set
    pour les List
    et pour les Map (tant qu'à faire)

Discussions similaires

  1. Que veut dire : for (int i = (1 << bits) - 1; i >= 0; --i)
    Par HNoury dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 08/08/2012, 18h52
  2. test.py : ValueError: invalid literal for int()
    Par black-falco dans le forum Django
    Réponses: 2
    Dernier message: 05/08/2011, 12h11
  3. [Débutant] invalid literal for int() with base 10: '\r'
    Par oodini dans le forum Général Python
    Réponses: 19
    Dernier message: 23/03/2011, 15h25
  4. invalid literal for int() with base 10:
    Par EricStib dans le forum Général Python
    Réponses: 9
    Dernier message: 05/01/2009, 13h22
  5. [Taglib] Equivalent boucle "for(int i ; i<10 ; i++ )
    Par Hikage dans le forum Taglibs
    Réponses: 2
    Dernier message: 22/03/2006, 15h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo