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

Dotnet Discussion :

Optimiser les performance en choissant bien les méthode du framework


Sujet :

Dotnet

  1. #1
    Membre éclairé Avatar de seb.49
    Profil pro
    ljgdfgdf
    Inscrit en
    Octobre 2002
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : ljgdfgdf

    Informations forums :
    Inscription : Octobre 2002
    Messages : 291
    Par défaut Optimiser les performance en choissant bien les méthode du framework
    Suite au post que j'ai vu hier (Utiliser string.ToLower() c'est mal !), je me suis amusé a compararer quelques méthode du framework afin de sélectionner les plus rapide et les mettre dans mon code.

    Voici mes premiers résultats :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (val.ToUpper().Contains("une".ToUpper()) == false)
    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (val.IndexOf("une",0,StringComparison.InvariantCultureIgnoreCase) == -1)


    VS (csb étant un StringBuilder et cs une simple string. La boucle est exécuter 3000 fois)


    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (string.IsNullOrEmpty(val))


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string a = "toto " + val + " toto";
    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string a = string.Format("toto {0} toto", val);

    Pour le coup la contaténation est plus rapide que le string.Format, pas très logique je trouve. A creuser...

    Pour Neptune et Nip
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if ((val == null) || (val == ""))
    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (string.IsNullOrEmpty(val))


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if ((val == null) || (val.Length == 0))
    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (string.IsNullOrEmpty(val))

    testé 1 000 fois et 3 000 000 de fois à chaque fois sinon le vainqueur était toujours différent

    Plus de détail ici http://dotnetperls.com/Content/IsNul...y-Samples.aspx

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    DateTime dtDateTime;
    try
    {
    dtDateTime = DateTime.Parse(val); //val étant une string contenant "01/01/2008"
    }
    catch
    {
    dtDateTime = DateTime.MinValue;
    }
    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    DateTime dtDateTime;
    DateTime.TryParse(val, out dtDateTime);


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      DateTime dtDateTime;
    try
    {
    dtDateTime = DateTime.Parse(val); //val étant une string contenant "01/01/a008"
    }
    catch
    {
    dtDateTime = DateTime.MinValue;
    }
    VS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    DateTime dtDateTime;
    DateTime.TryParse(val, out dtDateTime);


    Et vous, vous avez aussi des méthode à préconiser par rapport à d'autres ?

  2. #2
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Par défaut
    Bonjour.

    c'est pas mal ça.

    Pour le stringBuilder, c'est quelque chose d'assez connu, et ça s'explique facilement. A chaque fois que tu fait maChaine + " " + uneChaine, il y a 3 réallocations de chaine de caractères avec les recopies qui vont bien.

    Dans les bonnes pratiques il y a aussi l'utilisation de string.IsNullOrEmpty(maChaine) à la place de maChaine == ""

  3. #3
    Membre éclairé Avatar de seb.49
    Profil pro
    ljgdfgdf
    Inscrit en
    Octobre 2002
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : ljgdfgdf

    Informations forums :
    Inscription : Octobre 2002
    Messages : 291
    Par défaut
    Merci, je rajoute ça dans mon post

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2003
    Messages
    311
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 311
    Par défaut
    J'ai fait un post sur mon blog qui compare le temps d'exécution des différentes fonctions pour concaténer des chaines de caractères...

    Je n'ai pas les même résultats. J'ai eu comme conclusion qu'il vaut mieux utiliser StringBuilder quand on veut concaténer au moins 9 chaines de caractères...

  5. #5
    Membre éclairé Avatar de seb.49
    Profil pro
    ljgdfgdf
    Inscrit en
    Octobre 2002
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : ljgdfgdf

    Informations forums :
    Inscription : Octobre 2002
    Messages : 291
    Par défaut
    Je constate pas cela, c'est toujours StringBuilder qui gagne chez moi.

    D'autres on essayé ?

  6. #6
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Par défaut
    Citation Envoyé par zoubidaman Voir le message
    Je n'ai pas les même résultats. J'ai eu comme conclusion qu'il vaut mieux utiliser StringBuilder quand on veut concaténer au moins 9 chaines de caractères...
    ???
    pas vu ce genre de chose non plus.

    Dans les astuces également il y a l'utilisation (mais pas trop intensif quand même) de string.Format("toto {0} totot", maChaine); plutot que a = "toto " + maChaine + " totot";
    Normalement ça donne de meilleur résultat.

  7. #7
    Membre éclairé Avatar de seb.49
    Profil pro
    ljgdfgdf
    Inscrit en
    Octobre 2002
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : ljgdfgdf

    Informations forums :
    Inscription : Octobre 2002
    Messages : 291
    Par défaut
    Citation Envoyé par dev01 Voir le message
    ???
    Dans les astuces également il y a l'utilisation (mais pas trop intensif quand même) de string.Format("toto {0} totot", maChaine); plutot que a = "toto " + maChaine + " totot";
    Normalement ça donne de meilleur résultat.
    Normalement ? J'ai éditer mon post avec ton test et c'est la concaténation qui est plus rapide par rapport au string.Format.

  8. #8
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par seb.49 Voir le message
    Pour le coup la contaténation est plus rapide que le string.Format, pas très logique je trouve. A creuser...
    C'est contradictoire avec une constation précédente, à savoir qu'un StringBuilder est plus performant qu'un concaténation. Hors, String.Format() utilise un StringBuilder en interne... Il faudrait comparer avec un formatage pour en être certain.

  9. #9
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Par défaut
    Pour le stringbuilder c'est interessant de l'utiliser a partir de 5 concatenations: http://www.chinhdo.com/20070929/stringbuilder-part-2/

    Sinon je n'ai pas verifie la difference de perfs mais myString.Length == 0 est plus efficace que isnullorempty pour verifier si la chaine est vide (ce qui est logique puisque isnullorempty verifie 2 conditions contre une pour length mais meme si tu fais str == null || str.Length == 0, ca devrait etre plus rapide). Mais je suis extremement surpris par les differences de perfs: tu aurais fait str == null || str == "" pour comparer a IsNullOrEmpty j'aurais compris une telle difference mais la c'est etonnant. Tu veux pas mettre le code que tu utilises?

  10. #10
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par Nip Voir le message
    Sinon je n'ai pas verifie la difference de perfs mais myString.Length == 0 est plus efficace que isnullorempty pour verifier si la chaine est vide (ce qui est logique puisque isnullorempty verifie 2 conditions contre une pour length mais meme si tu fais str == null || str.Length == 0, ca devrait etre plus rapide).
    Je ne suis pas du tout d'accord avec toi. Tu ne peux tester la longueur avant de t'être assuré que la string n'est pas nulle.

    Et puis, voici ce que fait exactement le framework, je pense qu'on ne peut faire mieux en performance pour tester si une chaine est vide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static bool IsNullOrEmpty(string value)
    {
        if (value != null)
        {
            return (value.Length == 0);
        }
        return true;
    }

  11. #11
    Membre éclairé Avatar de seb.49
    Profil pro
    ljgdfgdf
    Inscrit en
    Octobre 2002
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : ljgdfgdf

    Informations forums :
    Inscription : Octobre 2002
    Messages : 291
    Par défaut
    Citation Envoyé par Nip Voir le message
    myString.Length == 0 est plus efficace que isnullorempty
    Mais si myString est null tu plantes. Bien sur tu a peut être un try catch mais la les performances sont a la ramasse.

    Regarde les test de conversion de date dans la post initial

    Citation Envoyé par Nip Voir le message
    Tu veux pas mettre le code que tu utilises?
    http://www.coldwire.net/blogs/toutou...de-code-c.aspx

  12. #12
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Par défaut
    Citation Envoyé par seb.49 Voir le message
    Normalement ? J'ai éditer mon post avec ton test et c'est la concaténation qui est plus rapide par rapport au string.Format.
    c'est tout l'interet du normalement.

    En fait la perte de perf de la méthode Fomart vient du vient du fait que la chaine est a chaque fois parsé afin de savoir ou se trouve les jetons à remplacer. Même si ensuite c'est un StringBuilder qui est utilisé, il n'empêche que la chaine est parsé a chaque fois.

    La seul et unique bonne réponse en terme de perf c'est d'utiliser directement un StringBuilder (mais ça tue la lisibilité, comme quoi le monde n'est pas parfait ), ou à la limite un Regex compilé (pas testé )

  13. #13
    Membre éclairé Avatar de seb.49
    Profil pro
    ljgdfgdf
    Inscrit en
    Octobre 2002
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : ljgdfgdf

    Informations forums :
    Inscription : Octobre 2002
    Messages : 291
    Par défaut
    Citation Envoyé par dev01 Voir le message
    c'est tout l'interet du normalement.

    En fait la perte de perf de la méthode Fomart vient du vient du fait que la chaine est a chaque fois parsé afin de savoir ou se trouve les jetons à remplacer. Même si ensuite c'est un StringBuilder qui est utilisé, il n'empêche que la chaine est parsé a chaque fois.

    La seul et unique bonne réponse en terme de perf c'est d'utiliser directement un StringBuilder (mais ça tue la lisibilité, comme quoi le monde n'est pas parfait ), ou à la limite un Regex compilé (pas testé )
    Merci pour ces précisions

  14. #14
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Par défaut
    Citation Envoyé par neptune Voir le message
    Je ne suis pas du tout d'accord avec toi. Tu ne peux tester la longueur avant de t'être assuré que la string n'est pas nulle.
    Tu peux ne pas etre d'accord etant donne que je parle explicitement de chaine vide. Quand je lis il n'y a la aucune verification de la nullite. Dans ce cas precis val.Length == 0 est de loin la meilleure option.

    Citation Envoyé par seb.49
    Mais si myString est null tu plantes. Bien sur tu a peut être un try catch mais la les performances sont a la ramasse.
    Totalement d'accord; si il y a necessite de tester la nullite alors la meilleure solution est le IsNullOrEmpty.

  15. #15
    Membre Expert Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Par défaut
    D'une manière générale, si on a besoin de faire de nombreux appels à la reflexion (en dehors de GetType() qui est optimisé), il vaut mieux faire appel à des méthodes dynamiques.

  16. #16
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Par défaut
    Juste pour revenir sur le Concatenation vs builder vs format, il ne faut pas tomber dans l'excès de dire que la concatenation simple est tout le temps mauvaise, puisque ce n'est pas le cas. La ou les performances d'un concat sont excecrables, c'est sur les accumulations (le fameux string s += // blabla). Dans ce cas precis, la concatenation est à bannir puisque il va allouer autant de chaine que de tour de boucle, ce qui est un gouffre en terme d'allocation (ce que met en exergue le bench de l'op).

    Le point est que pour une concatenation simple de moins de 4 strings, la solution du "+" (en interne String.Concat) est de loin la meilleure solution. 4 car Concat est prevue pour recevoir de 2 à 4 strings et ou objets. Jusqu'à 4 strings, Concat va utiliser exactement la meme machinerie qu'un Stringbuilder (à savoir FastAllocate[string ?]) et ne fera qu'une seule allocation, stringbuilder faisant la meme chose le cout de l'instanciation en plus. Un exemple :

    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
        class Program
        {
            static void Main(string[] args)
            {
                string[] strs = {"Tutu", "Toto", "Tata", "Tete"};
                Stopwatch sw = new Stopwatch();
     
                for (int j = 0; j < 10; j++)
                {
                    sw.Start();
                    for (int i = 0; i < 3000; i++)
                    {
                        StringBuilder sb = new StringBuilder();
                        foreach (string s in strs)
                            sb.Append(s);
                    }
                    sw.Stop();
                    Console.Write(j + " : " + sw.ElapsedTicks);
                    sw.Reset();
     
                    sw.Start();
                    for (int i = 0; i < 3000; i++)
                    {
                        string s = strs[0] + strs[1] + strs[2] + strs[3] + "Test" + "Test1" + "Test2";
                    }
                    sw.Stop();
                    Console.WriteLine(" Vs " + sw.ElapsedTicks);
                    sw.Reset();
                }
                Console.Read();
            }
    qui donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    0 : 12389 Vs 7017
    1 : 3573 Vs 4565
    2 : 3882 Vs 5194
    3 : 3266 Vs 5869
    4 : 2648 Vs 5091
    5 : 3684 Vs 5723
    6 : 3226 Vs 5101
    7 : 3703 Vs 4989
    8 : 3049 Vs 5674
    9 : 3134 Vs 6571
    [D'ailleurs il ne faudrait pas ecrire les constantes directement car elles seront surement preoptimisées en une seule chaine par csc)

    Maintenant commentez les trois dernieres literrales du concat, vous obtiendrez quelque chose comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    0 : 4881 Vs 2875
    1 : 4455 Vs 1408
    2 : 3169 Vs 1743
    3 : 2950 Vs 1840
    4 : 2941 Vs 1512
    5 : 2995 Vs 1730
    6 : 3070 Vs 1350
    7 : 3480 Vs 2044
    8 : 3150 Vs 1445
    9 : 3016 Vs 1727
    La difference etant due au fait que pour plus de 4 strings ce n'est plus Concat(string, string, string, string) qui est appelé mais la version avec un tableau Concat(string[]) et c'est cette allocation qui fait la difference avec la version builder.

    Bref, pour repeter ce que disais le lien plus haut, si <= 4 strings ou tableau de strings deja disponible et surtout pas d'accumulation (+= et for c'est le mal absolu ! =p) , l'utilisation du "+" est tres performante, dans les autres cas, le builder se revele bien plus adapté.

  17. #17
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2003
    Messages
    311
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 311
    Par défaut
    Il me semble avoir vu une page de blog qui faisait ce genre de tests sur différentes machines.

    Il s'avère que le même test ne donne pas toujours le même vainqueur en fonction de la configuration...

    Ca fait encore plus de choses à prendre en compte du coup

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 23/09/2009, 11h02
  2. [SQL2000] Les paquets de requêtes et les performances
    Par Etanne dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 19/03/2008, 17h57
  3. Réponses: 0
    Dernier message: 10/12/2000, 13h00

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