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

JavaScript Discussion :

Optimisation de boucle JS


Sujet :

JavaScript

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 10
    Par défaut Optimisation de boucle JS
    Bonjour a tous, je me demandais si il y avais un moyen d'effectuer cette réduction plus rapidement qu'en passant par une boucle (il peu y avoir 10000 element dans l'array) car ces dernières ont l'air de ralentir considérablement IE.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    tab_dn = new Array();
    for (var i=0;i<users.length;i++){
         tab_dn[i] = users[i]['dn'];
    }
    Merci

  2. #2
    Expert confirmé
    Avatar de le_chomeur
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2006
    Messages
    3 653
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 3 653
    Par défaut
    bonjour , tu peux tester ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    tab_dn = new Array();
    for (var i=0, l = users.length;i<l;i++){
         tab_dn.push(users[i]['dn']);
    }
    ou encore
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var tab_dn = new Array();
    var max = users.length;
    var i = 0 ;
    while(i!=max){
         tab_dn[i] = users[i]['dn'];
         i++;
    }

  3. #3
    Membre expérimenté Avatar de nod__
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 176
    Par défaut
    Je dirais même plus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var tab_dn = [];
    var i = users.length;
    while (i--) {
         tab_dn[i] = users[i]['dn'];
    }
    ( edit )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var tab_dn = [];
    var i = users.length;
    while (i--) {
         tab_dn.push(users[i]['dn']);
    }

  4. #4
    Membre Expert Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Par défaut différences de performance entre une boucle for et une boucle while, push et affectation
    Je ne jurerais de rien! Avec toutes les nouvelles versions de navigateurs on obtient des résultats moins clairs qu'avant j'ai l'impression. Document de test :
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <title>différences de performance entre une boucle for et une boucle while, push et affectation</title>
      <meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
      <style type="text/css">
      * {margin:0;padding:0;}
      body {margin:10px;background:#000;color:#ddd;font-size:1em;font-family:Helvetica, Arial, sans-serif;}
      </style>
    </head>
    <body>
      <p id="fl1">for (length recalculé) : </p>
      <p id="fl2">for (avec push et length recalculé) : </p>
      <p id="f1">for : </p>
      <p id="f2">for (avec push) : </p>
      <p id="w1">while : </p>
      <p id="w2">while (avec push) : </p>
      <script type="text/javascript">
      <!--
      var fl1 = document.getElementById("fl1");
      var fl2 = document.getElementById("fl2");
      var f1 = document.getElementById("f1");
      var f2 = document.getElementById("f2");
      var w1 = document.getElementById("w1");
      var w2 = document.getElementById("w2");
     
      var ti = new Array();
      ti.length = 100000;
     
      var t1a = new Array();
      var debut = new Date();
      for (var i=0; i<ti.length; i++) {
        t1a[i] = i;
      }
      var fin = new Date()
      fl1.firstChild.nodeValue = "for (length recalculé) : "+ (fin - debut) +" ms";
     
      var t1b = new Array();
      var debut = new Date();
      for (var i=0; i<ti.length; i++) {
        t1b.push(i);
      }
      var fin = new Date()
      fl2.firstChild.nodeValue = "for (avec push et length recalculé) : "+ (fin - debut) +" ms";
     
      var t2a = new Array();
      var debut = new Date();
      for (var i=0,imax=ti.length; i<imax; i++) {
        t2a[i] = i;
      }
      var fin = new Date()
      f1.firstChild.nodeValue = "for : "+ (fin - debut) +" ms";
     
      var t2b = new Array();
      var debut = new Date();
      for (var i=0,imax=ti.length; i<imax; i++) {
        t2b.push(i);
      }
      var fin = new Date()
      f2.firstChild.nodeValue = "for (avec push) : "+ (fin - debut) +" ms";
     
      var t3a = new Array();
      i = ti.length;
      debut = new Date();
      while(i--){
        t3a[i] = i;
      }
      fin = new Date()
      w1.firstChild.nodeValue = "while : "+ (fin - debut) +" ms";
     
      var t3b = new Array();
      i = ti.length;
      debut = new Date();
      while(i--){
        t3b.push(i);
      }
      fin = new Date()
      w2.firstChild.nodeValue = "while (avec push) : "+ (fin - debut) +" ms";
      //-->
      </script>
    </body>
    </html>

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 10
    Par défaut
    Merci a tous,
    En réalité le traitement est relativement long.
    (sous IE 7.0.5730.13 environ 3 a 4 secondes alors que sous firefox 3.5.2 210ms (estimé avec le profileur firebug) en moyenne )
    Et ceci après plusieurs heures optimisation déjà, je cherche maintenant a grappiller encore quelques millisecondes histoire de faire patienter les utilisateurs le moins possible, et pour le moment la ou j'ai gagner le plus de temps sous IE c'est en supprimant/allégeant les boucles.

    J'ai quand même du mal a comprendre pourquoi IE même si c'est certes une version qui date un peu plus que celle de mon Firefox met 20x plus de temps a exécuter un script qui est relativement peu complexe sur une page qui même si elle contient un formulaire contenant plusieurs milliers de champs reste d'une structure fort simple.

  6. #6
    Expert confirmé
    Avatar de le_chomeur
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2006
    Messages
    3 653
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 3 653
    Par défaut
    et en essayant d'externaliser le remplissage ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var t2a = new Array();
     
    var remplir = function(t){
      t2a[i] = i;
    }
     
    var tempo = null;
    for (var i=0,imax=ti.length; i<imax; i++) {
       tempo = new remplir(t);
    }

  7. #7
    Membre Expert Avatar de DoubleU
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 106
    Par défaut
    T'es sur que c'est pas plutot la partie effectuant le traitement a partir de ton tableau qui est long?

    Sinon essaie ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab_dn.push(users[i]['dn']);

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2009
    Messages
    354
    Détails du profil
    Informations personnelles :
    Localisation : France, Sarthe (Pays de la Loire)

    Informations forums :
    Inscription : Février 2009
    Messages : 354
    Par défaut
    concernat les boucles j'ai créer un petit bench sinon pour résumer, la meilleur syntaxe est celle-ci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var monTableau = ['val1', 'val2', ....];
     
    for(var i = -1 , e; e = monTableau[++i]){
       traitement ...
    }
    ou pour un while


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var monTableau = ['val1', 'val2', ....], i = -1, e;
     
    while(e = monTableau[++i]){
       traitement ...
    }
    il faut préciser que la condition doit retourner une valeur positive ... soit le double inverse boolean doit être à true (!!e = true), donc si ton tableau possède des valeur null ou indéfini, il faudra plus faire ça.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for(var i = -1 , l = monTableau.length, e; l > ++i;){
       e = monTableau[i];
       traitement ...
    }
    ou pour le while

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    var monTableau = ['val1', 'val2', ....], i = -1,  l =  monTableau.length, e;
     
    while(l > ++i){
       e = monTableau[i];
       traitement ...
    }
    j'allais oublier, le push fait perdre du temps, si tu dois enregistrer un résultat dans un autre tableau, soit si tu peux, utilise l'index du tableau d'origine, soit créer un index pour spéciale pour le nouveaux tableau, ou plus simple mais un peux moin performant ->

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var monTableau = ['val1', 'val2', ....], monAutreTableau = [], i = -1,  l =  monTableau.length, e;
     
    while(l > ++i){
       e = monTableau[i];
       monAutreTableau[monAutreTableau.length] = e;
       traitement ...
    }
    bye

  9. #9
    Membre Expert Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Par défaut
    J'ai déjà vu ce genre de syntaxe disant qu'elle est optimisée, mais quand j'essaie de al reproduire ça plante. Tu pourras peut-être me dire où j'ai faux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      var t4a = new Array();
    var debut = new Date();
    for (var i=-1,e; e=t4a[++i]) {
      t4a.push(i);
    }
    var fin = new Date()
    J'ai une erreur de syntaxe au niveau la boucle for dans tous les navigateurs (IE8 ; FF3.5 ; Opera 10 ; Safari 4).

    De plus, dans ton banc d'essai, tu ne parles pas de cette syntaxe.

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2009
    Messages
    354
    Détails du profil
    Informations personnelles :
    Localisation : France, Sarthe (Pays de la Loire)

    Informations forums :
    Inscription : Février 2009
    Messages : 354
    Par défaut
    salut, là ou ca plante, c'est que tu as oublié un ';' a la fin de tas zone conditionnelle , par exemple il est tout à fait possible de faire ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for(;;){
       if(machintruc)
           break;
    }
    sinon comme je l'ai dit si tu doit utiliser bcp d'item du tableau dans ton code , la syntaxe permettant de référencer cette item dans la zone conditionnelle est valable que si cette item n'a pas de valeur null, car sinon la condition est fausse...

    quand tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    var array = new Array();
    for(var i =-1, a; a=array[++i];){
        //traitement
    }
    il ne se produira aucune itération car le tableau est vide , est la condition -> a=array[++i] , renvoie la valeur de a , soit null.

    dans ce cas , et oui j'ai pas mit dans mon bench, le mieux est la syntaxe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var array = new Array(0,1,2,3,4,5,6,7);
    for(var i =-1, l = array.length, a; l > ++i;){
        a = array[i]
        //traitement
    }
    sinon au premier item, valant zéro, la condition serait passé à null, et donc aucune itération...

    voilà j'espère avoir été un peu plus claire bye!

  11. #11
    Membre Expert Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Par défaut
    En effet, j'oubliais le point-virgule et suis sûr que je l'oubliais déjà la première fois que j'étudiais cette syntaxe!

    Par contre, les résultats entre les deux boucles for n'est pas vraiment probant. Les performances dépendant du nombre d'itérations et du navigateurs. Je privilégierais donc celle-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (var i=0,imax=ti.length; i<imax; i++) {
      t2a[i] = i;
    }
    car, plus lisible.

  12. #12
    Membre Expert Avatar de DoubleU
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 106
    Par défaut
    Je ne suis pas vraiment (pas du tout meme ) d'accord avec toi kimjoa.

    Déja, ta méthodologie n'est pas bonne: tu ne testes qu'une seule fois chaque boucle et tu en déduis ton résultat. Le problème, c'est que si au moment ou tu fais untest, ton cpu est occupé a autre chose, ben les perf de ce test vont en prendre un coup, ce qui va entrainer un biais.

    Si tu fais la moyenne des durées sur plusieurs itérations, tu verras que le résultat est différent:
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    <html>
     
    	<body>
    		<script>
     
    		var tab = new Array();
    		for(var v=0;v<100000;v++) tab.push(v+2);
     
    		function timer(what)
    		{
    			var start = new Date();
    			what();
    			var stop = new Date();
    			return stop.getTime() - start.getTime()
    		}
     
    		function average(what, nb)
    		{
    			var t = 0;
    			for(var v=0; v<nb; v++)
    			{
    				t += timer(what);
    			}
    			return t/nb;
    		}
     
    		function f1()
    		{
    			for(var i = -1 , e; e = tab[++i];)
    			{
    				var foo = e+e;
    			}
    		}
     
    		function f2()
    		{
    			for(var i=0, e; i<tab.length; i++)
    			{
    				e = tab[i]; // pour accéder a l'élément, comme dans f1
    			}
    		}
     
    		function f3()
    		{
    			var foo = 0;
    			for(var i=tab.length,e; i>0;i--)
    			{
    				e = tab[i];
    			}
    		}
     
    		var n = 500;
     
    		console.log("f1", average(f1,n));
    		console.log("f2", average(f2,n));
    		console.log("f3", average(f3,n));
     
    		</script>
    	</body>
     
     
    </html>
    On obtient:
    Citation Envoyé par firebug
    f1 4.228
    f2 1.724
    f3 1.682
    Pourquoi cet écart? Parce que dans f1, pour invalider la comparaison, il faut soit que e soit NaN, undefined, null, false ou égal à 0 (j'ai rien oublié je crois ^^), c'est à dire faire une opération d'objets complexes pour certains d'entre eux.
    Dans f2, c'est une simple comparaison bit a bit entre 2 nombres.
    Dans f3, c'est une opération bit a bit entre 0 et un nombre, donc plus rapide que f2.

Discussions similaires

  1. Comment optimiser plusieurs boucles FOR-END imbriquées
    Par totoc1001 dans le forum MATLAB
    Réponses: 26
    Dernier message: 13/05/2007, 17h59
  2. [Tableaux] Optimisation de boucles
    Par xdoreau dans le forum Langage
    Réponses: 4
    Dernier message: 12/02/2007, 11h28
  3. Optimisation de boucle 'while..do'
    Par delphi5user dans le forum Delphi
    Réponses: 10
    Dernier message: 25/07/2006, 22h37
  4. Probleme optimisation de boucles
    Par panda31 dans le forum C
    Réponses: 13
    Dernier message: 06/04/2006, 15h10
  5. Réponses: 4
    Dernier message: 17/01/2006, 19h17

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