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

C# Discussion :

Performance boucle for


Sujet :

C#

  1. #1
    Membre éclairé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2004
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Service public

    Informations forums :
    Inscription : Février 2004
    Messages : 477
    Par défaut Performance boucle for
    Bonjour à tous,

    J'essai de comprendre pourquoi ma simple boucle for est lente.
    En commentaire le code initial que j'ai transformé en une imbrication de if else.
    Est ce que quelqu'un peut m'aider pour améliorer les temps de réponse ?

    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
     
     
    string[] sTab = new string[200000];
                string sXlsReturn = "";
     
                for (int i = 0; i < sTab.Length; i++)
                    sTab[i] = i.ToString();
     
                for (int i = 2; i <= sTab.Length - 2; i += 12)
                {             
                    sXlsReturn += "<tr>";
     
                    try
                    {
                        /*sXlsReturn +=
                            "<td>" + (i + 1 < sTab.Length ? (sTab[i + 1] != "" ? double.Parse(sTab[i + 1]).ToString() : sTab[i + 1]) + "</td>" : "</td>") +
                            "<td>" + (i + 3 < sTab.Length ? (sTab[i + 3] != "" ? double.Parse(sTab[i + 3]).ToString() : sTab[i + 3]) + "</td>" : "</td>") +
                            "<td>" + (i + 5 < sTab.Length ? (sTab[i + 5] != "" ? double.Parse(sTab[i + 5]).ToString() : sTab[i + 5]) + "</td>" : "</td>") +
                            "<td>" + (i + 7 < sTab.Length ? (sTab[i + 7] != "" ? double.Parse(sTab[i + 7]).ToString() : sTab[i + 7]) + "</td>" : "</td>") +
                            "<td>" + (i + 9 < sTab.Length ? (sTab[i + 9] != "" ? double.Parse(sTab[i + 9]).ToString() : sTab[i + 9]) + "</td>" : "</td>") +
                            "<td>" + (i + 11 < sTab.Length ? (sTab[i + 11] != "" ? double.Parse(sTab[i + 11]).ToString() : sTab[i + 11]) + "</td>" : "</td>");*/
     
                        if (i + 1 < sTab.Length)
                        {
                            if (sTab[i + 1] != "")
                                sXlsReturn = string.Concat(sXlsReturn, "<td>", double.Parse(sTab[i + 1]).ToString(), "</td>");
                            else sXlsReturn = string.Concat(sXlsReturn,"<td></td>");
                        }
     
                        if (i + 3 < sTab.Length)
                        {
                            if (sTab[i + 3] != "")
                                sXlsReturn = string.Concat(sXlsReturn, "<td>", double.Parse(sTab[i + 3]).ToString(), "</td>");
                            else sXlsReturn = string.Concat(sXlsReturn, "<td></td>");
                        }
     
                        if (i + 5 < sTab.Length)
                        {
                            if (sTab[i + 5] != "")
                                sXlsReturn = string.Concat(sXlsReturn, "<td>", double.Parse(sTab[i + 5]).ToString(), "</td>");
                            else sXlsReturn = string.Concat(sXlsReturn, "<td></td>");
                        }
     
                        if (i + 7 < sTab.Length)
                        {
                            if (sTab[i + 7] != "")
                                sXlsReturn = string.Concat(sXlsReturn, "<td>", double.Parse(sTab[i + 7]).ToString(), "</td>");
                            else sXlsReturn = string.Concat(sXlsReturn, "<td></td>");
                        }
     
                        if (i + 9 < sTab.Length)
                        {
                            if (sTab[i + 9] != "")
                                sXlsReturn = string.Concat(sXlsReturn, "<td>", double.Parse(sTab[i + 9]).ToString(), "</td>");
                            else sXlsReturn = string.Concat(sXlsReturn, "<td></td>");
                        }
     
                        if (i + 11 < sTab.Length)
                        {
                            if (sTab[i + 11] != "")
                                sXlsReturn = string.Concat(sXlsReturn, "<td>", double.Parse(sTab[i + 11]).ToString(), "</td>");
                            else sXlsReturn = string.Concat(sXlsReturn, "<td></td>");
                        }
                    }
                    catch (IndexOutOfRangeException) { }
                }
            }

  2. #2
    Membre éclairé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2004
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Service public

    Informations forums :
    Inscription : Février 2004
    Messages : 477
    Par défaut
    Il semblerait que StringBuilder soit mon ami ...

  3. #3
    Membre chevronné Avatar de WaterTwelve21
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2015
    Messages
    270
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2015
    Messages : 270
    Par défaut
    J'ai pas vraiment chercher à saisir ce que tu souhaites faire mais en effet Stringbuilder semble convenir.

    Cependant une chose me taraude :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double.Parse(sTab[i + 3]).ToString()
    Pourquoi convertir en double pour ensuite passer en string, sachant que sTab est déjà un tableau de string ?

  4. #4
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par WaterTwelve21 Voir le message
    J'ai pas vraiment chercher à saisir ce que tu souhaites faire mais en effet Stringbuilder semble convenir.

    Cependant une chose me taraude :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double.Parse(sTab[i + 3]).ToString()
    Pourquoi convertir en double pour ensuite passer en string, sachant que sTab est déjà un tableau de string ?
    Si c'est délibéré c'est peut-être un moyen de vérifier que la donnée en entrée est bien un double ? Mais dans ce cas ça vaudrait la peine de gérer explicitement l'erreur (FormatException).

  5. #5
    Membre chevronné Avatar de WaterTwelve21
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2015
    Messages
    270
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2015
    Messages : 270
    Par défaut
    Si c'est délibéré c'est peut-être un moyen de vérifier que la donnée en entrée est bien un double ?
    D'accord si on ne connaissait pas à l'avance la nature des entrées, cependant il rempli le tableau dans une boucle for en premier lieu

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for (int i = 0; i < sTab.Length; i++)
                    sTab[i] = i.ToString();
    La vérif' me semble inutile . (Je sais que tu as juste zappé, mais le message s'adresse à Pfeffer aussi )


    De plus je rajoute que du code entouré d'un try/catch est moins performant. Ton try/catch est inutile ici puisque tu fais déjà les vérifications.

    +

    ces tests sont inutiles, de la manière que tu as rempli ton tableau, un élément en champ vide est impossible.

  6. #6
    Expert confirmé

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par Pfeffer Voir le message
    Bonjour à tous,

    J'essai de comprendre pourquoi ma simple boucle for est lente.
    La concaténation de string est lente, car impose l'allocation d'une nouvelle chaine et la copie des deux chaînes à concaténer. Répéter des centaines de milliers de fois, c'est très gourmand en temps CPU et en mémoire. La bonne approche est affectivement d'utiliser un StringBuilder.

    Concernant le code, je suppose qu'il ne s'agit que d'un code d'exemple, ce qui expliquerait l'initialisation triviale de sTab et du double.Parse suivit d'un ToString, ainsi que les tests effetcutés sur sTab pour savoir quoi mettre dans les cellules. Si ce n'est pas le cas, et qu'il s'agit du code réel, tu peux également initialiser sTab avec la bonne valeur :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for (int i = 0; i < sTab.Length; ++i) 
    {
      // On aurait pu remplacer la variable i de type int par une variable de type double.
      // Mais c'est à déconseiller dans des boucles for, car il pourrait y avoir une accumulation d'erreurs
      // de précision. Il vaut donc mieux passer par un entier qui est converti ensuite en double.
       sTab[i] = Convert.ToDouble(i).ToString();
    }

    Et supprimer les tests et afficher directement sTab[i] dans les cellules.



    Sinon, le code est très répétitif. Il est possible de le réécrire beaucoup plus simplement et de manière plus compacte (et avec un StringBuilder) :
    Code C# : 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
     
    StringBuilder builder = new StringBuilder();
     
    for(int i = 0; <= (sTab.Length - 1) / 12; ++i) // Astuce : division entière, 14 / 12 = 1 ! Le "-1", c'est pour s'assurer que si la taille du tableau est un multilple de 12, que cela ne rajoute pas une itération inutile de la boucle.
    {
       builder.Append("<tr>");
       for(int j = 1; j <= 11; j += 2)
       {
          int k = i * 12 + j;
          if (k < sTab.Length && !String.IsNullOrEmpty(sTab[k]))
          {
             builder.Append("<td>");
             builder.Append(double.Parse(sTab[k]).ToString()); // Potentiellement, il peut y avoir des exceptions avec la méthode Parse ! Be carefull !!
             builder.Append("</td>");      
          }
          else
          {
             // On évite quelque concaténation inutile dans le cas où les cellules sont vides.
             // 1 seul appel à Append au lieu de 3. 
             builder.Append("<td></td>");
          }
       }
       builder.Append("</tr>"); // C'est un rajout de ma part. Il manquait la fermeture de la balise TR
    }

    Attention, code pas testé, mais c'est pour donner l'idée.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Boucle for dans un script cmd
    Par nicolas.ganache dans le forum Développement
    Réponses: 4
    Dernier message: 19/07/2004, 16h07
  2. Réponses: 3
    Dernier message: 06/07/2004, 10h21
  3. [Debutant] Batch et Boucle for
    Par ludovic.fernandez dans le forum Scripts/Batch
    Réponses: 8
    Dernier message: 06/05/2004, 19h21
  4. [Swing][boucles] for, do, if .....comment faire simple?
    Par chastel dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 02/05/2004, 22h49
  5. [langage] boucle "for" modification du pas
    Par K-ZimiR dans le forum Langage
    Réponses: 4
    Dernier message: 29/04/2004, 11h54

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