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 - Surprise avec l'operateur +


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Par défaut Performance - Surprise avec l'operateur +
    Bonjour,

    Suite à une étude sur les meilleurs pratiques autour des chaines de caractères, j'en ai conclu que l'opérateur "+" était une très bonne chose. A savoir :
    • Les litteraux sont concaténés à la compilation
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      string s1 = "Cette Chaine sera concaténée " +
                  "lors de la compilation. L'utilisation " +
                  "du \"+\" augmente la lisibilité.";
    • Les autres concatenations sont remplacées par un String.Concat qui est très performant. Ce qui signifie que ce code
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      string s1 = "Toutes les ";
      string s2 = "chaines sont ";
      string s3 = "connues avant ";
      string s4 = "l'operation de ";
      string s5 = "concatenation ";
      string s6 = s1 + s2 + s3 + s4 + s5 ;
      génère exactement le même MSIL que le code suivant.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      string s1 = "Toutes les ";
      string s2 = "chaines sont ";
      string s3 = "connues avant ";
      string s4 = "l'operation de ";
      string s5 = "concatenation ";
      string s6 = String.Concat(s1, s2, s3, s4, s5);
      a savoir, génération d'un tableau de string (car au dela de 4 arguments String.Concat passe par un tableau), puis appel a String.Concat :
      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
      IL_0187:  ldc.i4.5
      IL_0188:  newarr     [mscorlib]System.String
      IL_018d:  stloc.s    CS$0$0000
      IL_018f:  ldloc.s    CS$0$0000
      IL_0191:  ldc.i4.0
      IL_0192:  ldloc.s    s1
      IL_0194:  stelem.ref
      IL_0195:  ldloc.s    CS$0$0000
      IL_0197:  ldc.i4.1
      IL_0198:  ldloc.s    s2
      IL_019a:  stelem.ref
      IL_019b:  ldloc.s    CS$0$0000
      IL_019d:  ldc.i4.2
      IL_019e:  ldloc.s    s3
      IL_01a0:  stelem.ref
      IL_01a1:  ldloc.s    CS$0$0000
      IL_01a3:  ldc.i4.3
      IL_01a4:  ldloc.s    s4
      IL_01a6:  stelem.ref
      IL_01a7:  ldloc.s    CS$0$0000
      IL_01a9:  ldc.i4.4
      IL_01aa:  ldloc.s    s5
      IL_01ac:  stelem.ref
      IL_01ad:  ldloc.s    CS$0$0000
      IL_01af:  call       string [mscorlib]System.String::Concat(string[])


    De plus, String.Concat (donc l'operateur "+" également) s'execute deux fois plus rapidement qu'un String.Format ou qu'un StringBuilder, et utilise également deux fois moins de mémoire que ces deux instructions (PerfView).

    En ce qui me concerne l'histoire devrait s'arretter la : l'operateur "+" n'est pas contre-indiqué, voir même mieux que les autres. Mais il parrait que Mr Microsoft déconseille son utilisation, et que Mr Resharper le remplace par String.Format() parce qu'il serait le saint graal de la performance .
    Donc si un expert pouvait, soit, confirmer mes observations, soit, expliquer où je me trompe, ce serait super sympa.

  2. #2
    Membre chevronné
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2008
    Messages
    381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2008
    Messages : 381
    Par défaut
    Merci pour l'information! C'est vraiment bon à savoir!

  3. #3
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    J'imagine que l'opérateur + est en fait une conversion implicite retournant un string et qu'il s'agit en effet d'un "string.Concat" dans la fonction.

    Il me semble que le stringbuilder est plus performant lors de nombreuses modifications (je sais il est immuable) sur une chaine string (souvent dans une boucle).
    Le problème de modifier 1000 fois un string est qu'il va créer 1000 objets en mémoire avec les couts de création et le ramasse miette qui devra les traiter.

  4. #4
    Membre éprouvé Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Par défaut
    Merci pour vos réponses.
    Effectivement, je n'ai pas voulu assommer tout le monde avec la totalité de l'étude. Mais dès qu'on est dans une boucle de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // CODE EXEMPLE. PAS FAUX MAIS IL Y A PLUS SIMPLE.
    static string ConcatWithStringBuilder(List<String> stringList)
    {
        StringBuilder sb = new StringBuilder();
        foreach (string s in stringList)
        {
            sb.Append(s);
        }
        return sb.ToString();
    }
    CODE EXEMPLE. PAS FAUX MAIS IL Y A PLUS SIMPLE.
    il est préférable d'utiliser les StringBuilder.
    Il ne faut surtout pas faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // NE PAS UTILISER CE CODE !
    static string ConcatPerso(List<String> stringList)
    {
        string str = string.Empty;
        foreach (string s in stringList)
        {
            str += s;
        }
        return str;
    }
    // NE PAS UTILISER CE CODE !
    Pour être plus précis, ma question serait plutot pourquoi ne pas utiliser l'opérateur "+" (selon Microsoft) et pourquoi préférer la fonction String.Format() (selon Resharper) ?

  5. #5
    Membre Expert Avatar de jopopmk
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    1 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 1 856
    Par défaut
    Salut,

    dans le cas de la boucle, le StringBuilder est plus performant quelque soit le nombre d'itérations, ou il y a un palier ?

  6. #6
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    Je ne sais pas pourquoi il le faudrait mais je trouve ça bien de se poser la question. Voici quelques autres tests de performances qui vont dans ton sens.

    http://www.dotnetperls.com/string-concat
    http://jacksondunstan.com/articles/3015
    http://weblogs.asp.net/jevgeni/appen...-stringbuilder

    Peut être que les méthodes de concaténation on été optimiser lors d'une monté de version du FrameWork ?

    String.Format utilise en interne un StringBuilder, la question doit donc être la même :
    Quand dois je utiliser "+" (ou concat) et quand dois je utiliser StringBuilder (ou StringFormat).

    Pour une opération simple "a" + "b" la concaténation "+" est plus rapide du au cout de création de l'objet StringBuilder. StringFormat est donc déconseillé pour des questions de performances.

  7. #7
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2016
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2016
    Messages : 64
    Par défaut
    Je ne saurais pas dire pourquoi l'un est plus performant que l'autre (d'expérience je sais que la concaténation l'est presque toujours). Par contre, je sais pourquoi dans certaines situations je préfère toujours string.Format.
    Honnêtement, dans ma vie professionnelle je n'ai jamais rencontré de cas de figure où il fallait que je concatène des strings plusieurs dizaines de milliers de fois dans une boucle... et, de surcroît, avec le souci de gratter seulement quelques millisecondes. SI c'était le cas je ferais du C++.
    Par contre, il m'arrive tous les jours de travailler par exemple avec des IHM multilingues. Un exemple tout bête : l'affichage du nom - prénom d'un utilisateur.
    Sur la même appli, en français on veut le prénom puis le nom. En Chinois et en japonais, c'est le contraire.
    Avec string.Format mon code ne change pas ; parce que dans mes resx. je vais mettre par ex. une ressource "UserNameFormat" valant "{0} {1}" pour la ressource française, et "{1} {0}" pour la ressource Chinoise. Dans le code qui va l'afficher je vais indifféremment appeler "string.Format(maResource, monPrenom, monNom)".
    A mon avis c'est ça le truc : le choix dépend de la finalité, c'est une question d'architecture plus que de performance.

  8. #8
    Membre éprouvé Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Par défaut
    Merci pour vos réponses

    jopopmk
    dans le cas de la boucle, le StringBuilder est plus performant quelque soit le nombre d'itérations, ou il y a un palier ?
    Pas de palier. Dès 2 chaines, String.Concat est 2 fois plus rapide que StringBuilder
    Nombre 2 3 4 5 6
    String.Concat 0,252 0,403 0,544 0,721 0,86
    StringBuilder 0,734 0,923 1,289 1,457 1,859
    StringFormat 0,733 0,949 1,325 1,509 1,878
    Concatenation de 2 à 6 chaines de 4096 caractères générées aléatoirement. Test reproduit 100.000 fois. Resultat en seconde)


    ericlm128
    Je ne sais pas pourquoi il le faudrait mais je trouve ça bien de se poser la question. Voici quelques autres tests de performances qui vont dans ton sens.
    • dotnetperls => http://www.dotnetperls.com/string-concat
      Va dans mon sens. Il parle de String.Join que je vais observer plus en détail avec String.Format (voir le msil)
    • jacksondunstan => http://jacksondunstan.com/articles/3015
      Très agréable à lire.
      Va dans mon sens, mais une reponse à la fin donne un cas ou string.format est plus rapide (de peu) dans le cas où il est utilisé pour faire ce qu'il doit faire : Du formatage d'argument. Je vais également ajouter un cas de test qui tendrait à valider cette théorie.
    • Jevgeni Borozna's blog => http://weblogs.asp.net/jevgeni/appen...-stringbuilder
      Les exemples pris sont vraiment au désavantage du "+=" et du String.Format(). Deux bons exemples de ce qu'il ne faut pas faire et quand utiliser un StringBuilder



    Romka
    A mon avis c'est ça le truc : le choix dépend de la finalité, c'est une question d'architecture plus que de performance. .
    Merci pour la facon de faire. Moi qui ais toujours évité d'utiliser cette fonction, peut être qu'un jour... . Ici le problème est vraiment la performance. Et surtout la génération minimale de dechet.

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

Discussions similaires

  1. probleme avec les operateurs de comparaison
    Par vanilla94 dans le forum Langage
    Réponses: 11
    Dernier message: 13/11/2006, 11h18
  2. Réponses: 2
    Dernier message: 05/12/2005, 13h05
  3. [debutant]probleme avec l'operateur +
    Par Battosaiii dans le forum Débuter
    Réponses: 9
    Dernier message: 17/11/2005, 01h29
  4. petite surprise avec le DOM
    Par sekaijin dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 03/10/2005, 09h36
  5. Problème performance SELECT avec jointure
    Par Netgamer dans le forum Requêtes
    Réponses: 7
    Dernier message: 05/08/2005, 10h20

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