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

VB.NET Discussion :

Performances en VB.NET


Sujet :

VB.NET

  1. #1
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut Performances en VB.NET
    Bonjour,

    VB.NET propose différentes façon de faire les choses... qu'est-ce qui est le plus rapide ?

    J'ai fait un benchmark maison et les résultats sont très instructifs.

    J'ai ensuite optimisé quelques uns de mes programmes (déjà optimisés du point de vue algo et mathématiques) qui se sont alors montrés entre 5 et 25 fois plus rapide ... c'est super mais ça veut dire aussi qu'avant je codais en VB.NET comme une merde

    Mon programme de benchmark est ici en pièce jointe avec le code source : VB-NET-BENCH.zip

    Qu'en pensez-vous ? Avez-vous des autres idées de fonction VB à tester ?

    Voici le résultat du benchmark :

    NB : les tests ont été réalisés avec le fichier .EXE release ; dans le projet Option Explicit est à ON et Option Strict est à ON également

    === VERIF CHAINE NULLE ===
    Nombre de tests : 30.000.000
    106ms : If s <> ""
    158ms : If s <> vbNullString
    24ms : If len(s) <> 0
    33ms : If Not String.IsNullOrEmpty(s)
    16ms : If s.Length <> 0

    === CRÉATION CHAINE NULLE ===
    Nombre de tests : 60.000.000
    47ms : s = ""
    33ms : s = vbNullString
    33ms : s = String.Empty

    === CONCATENATION CHAINE ===
    Nombre de tests : 50.000
    442ms : s1 = s1 & "a"
    426ms : s1 &= "a"
    0ms : s2.Append("a") : s1 = s2.ToString
    Nombre de tests : 5.000
    0ms : s2.Append("a" & "b" & "c" & "d" & "e" & "f" & "g" & "h" & "i" & "j") : s1 = s2.ToString

    === COMPARAISON CHAINE avec s1 = s2 ===
    Nombre de tests : 2.000.000
    11ms : s1 = s2
    184ms : String.Compare(s1, s2) = 0
    5ms : String.CompareOrdinal(s1, s2) = 0
    4ms : String.Equals(s1, s2)

    === COMPARAISON CHAINE avec s1 <> s2 ; len(s1) = len(s2) ===
    Nombre de tests : 2.000.000
    50ms : s1 = s2
    174ms : String.Compare(s1, s2) = 0
    18ms : String.CompareOrdinal(s1, s2) = 0
    13ms : String.Equals(s1, s2)

    === COMPARAISON CHAINE avec s1 <> s2 ; len(s1) <> len(s2) ===
    Nombre de tests : 2.000.000
    41ms : s1 = s2
    178ms : String.Compare(s1, s2) = 0
    17ms : String.CompareOrdinal(s1, s2) = 0
    4ms : String.Equals(s1, s2)

    === COMPARAISON CHAINE IGNORER CASSE avec s1 = s2 ===
    Nombre de tests : 2.000.000
    445ms : UCase(s1) = UCase(s2)
    416ms : s1.ToUpper = s2.ToUpper
    225ms : UCase(s1) = s2
    181ms : String.Compare(s1, s2, True) = 0
    6ms : String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)

    === COMPARAISON CHAINE IGNORER CASSE avec s1 <> s2 ; len(s1) = len(s2) ===
    Nombre de tests : 2.000.000
    454ms : UCase(s1) = UCase(s2)
    417ms : s1.ToUpper = s2.ToUpper
    224ms : UCase(s1) = s2
    175ms : String.Compare(s1, s2, True) = 0
    65ms : String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)

    === COMPARAISON CHAINE IGNORER CASSE avec s1 <> s2 ; len(s1) <> len(s2) ===
    Nombre de tests : 2.000.000
    455ms : UCase(s1) = UCase(s2)
    420ms : s1.ToUpper = s2.ToUpper
    224ms : UCase(s1) = s2
    183ms : String.Compare(s1, s2, True) = 0
    8ms : String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)

    === APPELS BYVAL BYREF - VALEURS DANS CALL ===
    Nombre de tests : 100.000.000
    78ms : Call Sub1(A As Integer, B As Double, C As String)
    55ms : Call Sub2(ByVal A As Integer, ByVal B As Double, ByVal C As String)
    55ms : Call Sub3(ByRef A As Integer, ByRef B As Double, ByRef C As String)
    55ms : Call Sub4(ByVal A As Integer, ByVal B As Double, ByRef C As String)

    === APPELS BYVAL BYREF - VARIABLES ===
    Nombre de tests : 100.000.000
    70ms : Call Sub1(A As Integer, B As Double, C As String)
    55ms : Call Sub2(ByVal A As Integer, ByVal B As Double, ByVal C As String)
    55ms : Call Sub3(ByRef A As Integer, ByRef B As Double, ByRef C As String)
    55ms : Call Sub4(ByVal A As Integer, ByVal B As Double, ByRef C As String)

    === COLLECTION VS LIST(OF ) / FOR EACH ===
    Nombre de tests : 1.000.000
    213ms : Collection - Construction et For Each
    94ms : List(Of ) - Construction et For Each

    === COLLECTION VS LIST(OF ) / .ITEM(I) ===
    Nombre de tests : 10.000
    200ms : Collection - Construction et For i
    0ms : List(Of ) - Construction et For i

    === LIST(OF ) : FOR EACH / FOR I .ITEM(I) ===
    Nombre de tests : 10.000.000
    58ms : For Each
    15ms : For i

    === OPÉRATEURS += ===
    Nombre de tests : 50.000.000
    56ms : x = x + 1
    41ms : x += 1

    === OPÉRATEURS -= ===
    Nombre de tests : 50.000.000
    62ms : x = x - 1
    41ms : x -= 1

    === OPÉRATEURS *= ===
    Nombre de tests : 50.000.000
    72ms : x = x * 3
    55ms : x *= 3

    === OPÉRATEURS /= ===
    Nombre de tests : 50.000.000
    45ms : x = x / 3
    29ms : x /= 3

    === / CTE VS * CTE ===
    Nombre de tests : 100.000.000
    72ms : z = x / 2
    55ms : z = x * 0.5

    === / VAR VS * VAR ===
    Nombre de tests : 100.000.000
    78ms : z = x / y
    54ms : z = x * y

    === / VAR VS * VAR II ===
    Nombre de tests : 10.000.000
    208ms : zi = xi / y avec y = i
    61ms : zi = xi * y avec y = 1/i

    === FONCTIONS MATHÉMATIQUES ===
    Nombre de tests : 80.000.000
    15ms : +
    15ms : -
    10ms : *
    112ms : /
    100ms : SQRT
    528ms : SIN
    624ms : COS
    776ms : TAN
    476ms : LOG
    416ms : ASIN
    452ms : ACOS
    872ms : ATAN

    A +
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    il faut en effet tester différentes manières de faire quelque chose quand on a besoin de performances
    le stringbuilder est connu pour la concaténation

    après les temps donnés ne sont pas fixes, quand on essaye plusieurs fois quelque chose le temps change
    et x = x + 1 et x += 1 n'ont aucune raison d'être différent en performance, étant compilés de la même manière (enfin l'inverse serait étonnant)
    (parfois l'un est plus rapide que l'autre, parfois l'inverse)
    donc quand les temps sont proches on ne peut pas forcément en déduire une différence de performance

    le mieux pour faire des comparaisons et une moyenne sur plusieurs (beaucoup ?) essais (sans forcément compter le 1er, qui peut contenir le temps de compilation)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Quand on recherche la performance, on a parois intérêt à remplacer une procédure système de haut niveau par des procédures maison.

    Récément pour améliorer les performances d'une lecture de fichier binaire d'entiers, j'ai remplacé le BinaryReader par des ReadBytes suivis de recomposition des entiers depuis les octets lus ==> performance plus que doublée.

    Edit: As-tu compilé en version "Debug" ou en "Release" ?
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  4. #4
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 192
    Points : 28 073
    Points
    28 073
    Par défaut
    Moi, perso, là en première lecture, il y a 2 points qui m'interpellent

    - les appels de fonctions : Je ne comprend pas la différence de temps entre les call sub1 et call sub2, les 2 étant strictement identique (les byval sont implicite dans le call sub1, le compilateur agit comme s'ils y étaient)
    - le second point c'est les temps à 200 voire 400ms sur des instructions pour tant relativement simples

    Quoiqu'il y aurait aussi à débattre sur le fait de continuer à utiliser des instructions VB6 en .Net tel que les vbNullString ou UCase
    Tu dis
    dans le projet Option Explicit est à ON et Option Strict est à ON également
    et moi je rajoute dans tous mes projets, et impose dans les projets que je gère Interdiction d'utiliser la librairie Microsoft.VisualBasic
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  5. #5
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Quoiqu'il y aurait aussi à débattre sur le fait de continuer à utiliser des instructions VB6 en .Net tel que les vbNullString ou UCase
    déjà dit mais les 3/4 des fonctions héritées de vb6 sont soit des instructions du langage soit utilisent les fonctions du framework (dixit code source), ce ne sont alors que des raccourcis, donc rien de mal à ca je pense
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    Note: je n'ai pas regardé le code (flemme de télécharger + ouvrir un zip on va dire )

    Pour moi l'intérêt d'un tel bench est relative quand on voit par exemple un écart de 20ms sur 50000000 de tests soit 4e-7ms par test en moyenne ou 80000000 d'Atan qui prenne 872ms soit 1.09e-5ms par Atan je me demande ce qu'on veut vraiment gagner par cette approche.

    Surtout que certains tests me paraissent biaisé en amont, par exemple pour s2.Append("a" & "b" & "c" & "d" & "e" & "f" & "g" & "h" & "i" & "j") il y a de fortes chances que le compilo (ou le JIT) concatène ces littéraux en amont de l'exécution réelle du code. De même qu'il faudrait vérifier le code généré (voire le code JITté ou encore le résultat d'un NGEN) vérifier si la mesure n'est pas perturbée par autre chose (venant du système) si l'on a bien lancé une fois chaque tests sans mesure (pour laisser le JIT faire son boulot lors de la première exécution) ...

    Après il y a encore d'autres choses qui peuvent jouer, si on désactive la gestion des overflows sur les opérations numériques ça aura vraisemblablement un impact par exemple.

    Mais surtout il n'y a pas que la vitesse que l'on peut chercher à optimiser, il y a la mémoire (la "pression" sur le GC notamment), la bande-passante, les accès (réseaux, fichier etc.) bref tout ça pour dire que l'optimisation ça se fait après détection d'un réel problème (ralentissement, latence) dans une section de code critique (parce vouloir gagner 100ms sur de l'UI ça sert à rien) analyse de cette section, profilage, etc. et une fois qu'on a trouvé le où et le pourquoi on peut envisager quelles solutions s'offrent à nous, là, pour moi, c'est un peu mettre la charrue avant les boeufs.

    Quant au sujet des "méthodes VB6" c'est certes un sujet maintes fois abordé, et je suis à cheval entre sevyc64 et Pol63 (je devrais peut-être ajouter un 63.5 à la fin de mon pseudo ) je n'ai rien contre ce sont des méthodes .Net (et certaines ont même des recommandations dans la MSDN [des articles qui commencent à dater, je le concède] parce que faisant des vérifications avant d'appeler les méthodes .Net classique ; elles peuvent court-circuiter l'exécution et se révéler plus performantes et/ou plus propices à être optimisées par le JIT (mais je dirais qu'on s'en fiche surtout parce que c'est que quand on a décelé un problème qu'on en cherche la cause comme dit précédemment).
    Le seul, cas où je rejoins sevyc64 c'est par rapport à l'approche pour les débutants qui ont tendance à en abuser (croyant souvent qu'il s'agit de fonctions libres) et perdent ainsi de vue (ou s'éloignent avant même d'y entrer) la conception orientée objets.
    De toute façon, souvent, même sans le savoir on utilise cet espace de nom (du moins sa partie "CompilerServices") par exemple lorsque l'on fait If chaine1 = chaine2 Then
    Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
    À quelle heure dormez-vous ?
    Censément, quelqu'un de sensé est censé s'exprimer sensément.

  7. #7
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    Content de voir que le sujet fait réagir !

    Je bosse sur 3 applis qui font beaucoup de calcul et du dessin, les performances comptent ; ces tests m’ont aidé. Pour VB5 / VB6 il y a le très bon site VBSPEED mais il manque la même chose pour VB.NET

    Pour répondre aux questions :

    - Les tests sont fait en exécutant l’.EXE release (depuis l’IDE ou en lançant l’.EXE debug, les résultats sont différents)

    - Mon programme se présente sous forme d’une fenêtre avec un bouton pour chaque test ; cela permet de recommencer les tests plusieurs fois de suite comme on veut de façon à voir si les résultats ne varient pas ; quand on clique sur un bouton, le résultat du test s’affiche dans une boîte de dialogue et il est copié dans le presse-papier.

    - x += 1 et les fonctions similaires sont toutes plus rapides que leur version x = x + 1 ; elles ne sont donc pas codées pareil lors de la compilation

    - « j'ai remplacé le BinaryReader par des ReadBytes suivis de recomposition des entiers depuis les octets lus ==> performance plus que doublée. » => très intéressant ! il va falloir que je teste les fonctions sur les fichiers

    - « Je ne comprends pas la différence de temps entre les call sub1 et call sub2, les 2 étant strictement identique (les byval sont implicite dans le call sub1, le compilateur agit comme s'ils y étaient) » je suis moi aussi surpris, mais les tests montrent qu’il y a une différence je ne sais pas pourquoi

    - « 80000000 d'Atan qui prenne 872ms soit 1.09e-5ms par Atan je me demande ce qu'on veut vraiment gagner par cette approche. » => quand on fait des calculs pour chaque pixel d’une grosse image avec des boucles contenant des fonctions mathématiques le moindre µs compte :-)

    - « l'optimisation ça se fait après détection d'un réel problème (ralentissement, latence) dans une section de code critique » => oui c’est pour ça que j’ai fait ce bench, car les applis sur lequels je bosse possèdent des fonctions gourmandes en calcul

    - « Quant au sujet des méthodes VB6 c'est certes un sujet maintes fois abordé » => en effet, et dommage que la documentation DOT.NET ne donne pas la performance des instructions, et qu’elle ne distingue pas les « bonnes » fonctions VB6 traduites en .NET et les « mauvaises » qui sont très lentes et là uniquement pour permettre de réutiliser du code.

    - « Surtout que certains tests me paraissent biaisé en amont, par exemple pour s2.Append("a" & "b" & "c" & "d" & "e" & "f" & "g" & "h" & "i" & "j") il y a de fortes chances que le compilo (ou le JIT) concatène ces littéraux en amont de l'exécution réelle du code. » => oui c’est ennuyeux, d’ailleurs pour d’autres tests j’ai dû compliquer certains tests pour éviter les biais liés à l’optimisation automatique.

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  8. #8
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 192
    Points : 28 073
    Points
    28 073
    Par défaut
    Citation Envoyé par Sehnsucht Voir le message
    quand on voit par exemple un écart de 20ms sur 50000000 de tests soit 4e-7ms par test en moyenne ou 80000000 d'Atan qui prenne 872ms soit 1.09e-5ms par Atan je me demande ce qu'on veut vraiment gagner par cette approche.
    electroremy, peux-tu nous confirmer ce point, parce que là effectivement ça changerait tout.

    Les 20ms c'est bien le temps moyen d'un seul test calculé sur la base de 50000000 tests et non pas le temps total d’exécution des 50000000 tests.
    Parce que sinon, si c'est des temps cumulés, ils sont très largement raisonnables, même les plus élevés et le sujet en perd du coup tout son intérêt.

    Après reste à voir comment est fait la mesure (j'ai pas non plus ouvert le code) car, sous Windows, tout temps d’exécution mesuré à moins de 20ms sans utiliser les QueryPerformanceCounter mais basé sur l'horloge système n'est que pure fantaisie et n'a aucune signification
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  9. #9
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Les 20ms c'est bien le temps moyen d'un seul test calculé sur la base de 50000000 tests et non pas le temps total d’exécution des 50000000 tests.
    Parce que sinon, si c'est des temps cumulés, ils sont très largement raisonnables, même les plus élevés et le sujet en perd du coup tout son intérêt.

    Après reste à voir comment est fait la mesure (j'ai pas non plus ouvert le code) car, sous Windows, tout temps d’exécution mesuré à moins de 20ms sans utiliser les QueryPerformanceCounter mais basé sur l'horloge système n'est que pure fantaisie et n'a aucune signification
    Les temps que je donne correspondent à la durée totale de chaque test, par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Nombre de tests : 50.000
    442ms : s1 = s1 & "a"
    signifie que les 50.000 exécutions de s1 = s1 & "a" ont pris au total 442ms

    La notion de "temps raisonnable" dépend de l'appli... si c'est dans une procédure qui est exécuté pour chaque pixel d'une image c'est super critique :-P

    Par exemple, dans un programme de dessin j'ai remplacé les Collections par des List(Of xxx) ce qui m'a permis de ne plus avoir de liaison tardive et l'appli tourne 10 fois plus vite

    Citation Envoyé par sevyc64 Voir le message
    Après reste à voir comment est fait la mesure (j'ai pas non plus ouvert le code) car, sous Windows, tout temps d’exécution mesuré à moins de 20ms sans utiliser les QueryPerformanceCounter mais basé sur l'horloge système n'est que pure fantaisie et n'a aucune signification
    Je mesure le temps avec monStopWatch.ElapsedMilliseconds ; donc c'est pas bon ?

    Si ce n'est pas bon peux tu me donner un exemple de mesure de temps correcte en VB.NET ?

    Merci A+
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  10. #10
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    j'ai modifié mon programme pour :
    - utiliser QueryPerformanceCounter pour la mesure de temps
    - afficher le temps d'execution par instruction en ns (en faisant la moyenne) ce qui est mieux pour comparer

    Le programme mis à jour ici : VB-NET-BENCH2.zip

    Voici les résultats, faits avec l'executable release, qui sont plus logiques :

    === VERIF CHAINE NULLE ===
    3,528 ns : If s <> ""
    5,246 ns : If s <> vbNullString
    0,825 ns : If len(s) <> 0
    1,108 ns : If Not String.IsNullOrEmpty(s)
    0,559 ns : If s.Length <> 0

    === CRÉATION CHAINE NULLE ===
    0,792 ns : s = ""
    0,556 ns : s = vbNullString
    0,553 ns : s = String.Empty

    === CONCATENATION CHAINE ===
    8815,882 ns : s1 = s1 & "a"
    8427,985 ns : s1 &= "a"
    5,992 ns : s2.Append("a") : s1 = s2.ToString

    210,552 ns : s2.Append("a" & "b" & "c" & "d" & "e" & "f" & "g" & "h" & "i" & "j") : s1 = s2.ToString

    === COMPARAISON CHAINE avec s1 = s2 ===
    4,793 ns : s1 = s2
    87,313 ns : String.Compare(s1, s2) = 0
    2,449 ns : String.CompareOrdinal(s1, s2) = 0
    2,576 ns : String.Equals(s1, s2)

    === COMPARAISON CHAINE avec s1 <> s2 ; len(s1) = len(s2) ===
    23,722 ns : s1 = s2
    88,504 ns : String.Compare(s1, s2) = 0
    9,416 ns : String.CompareOrdinal(s1, s2) = 0
    6,995 ns : String.Equals(s1, s2)

    === COMPARAISON CHAINE avec s1 <> s2 ; len(s1) <> len(s2) ===
    23,920 ns : s1 = s2
    90,909 ns : String.Compare(s1, s2) = 0
    9,231 ns : String.CompareOrdinal(s1, s2) = 0
    2,845 ns : String.Equals(s1, s2)

    === COMPARAISON CHAINE IGNORER CASSE avec s1 = s2 ===
    209,578 ns : UCase(s1) = UCase(s2)
    206,909 ns : s1.ToUpper = s2.ToUpper
    111,770 ns : UCase(s1) = s2
    90,966 ns : String.Compare(s1, s2, True) = 0
    3,383 ns : String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)

    === COMPARAISON CHAINE IGNORER CASSE avec s1 <> s2 ; len(s1) = len(s2) ===
    219,908 ns : UCase(s1) = UCase(s2)
    204,889 ns : s1.ToUpper = s2.ToUpper
    110,581 ns : UCase(s1) = s2
    87,781 ns : String.Compare(s1, s2, True) = 0
    33,181 ns : String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)

    === COMPARAISON CHAINE IGNORER CASSE avec s1 <> s2 ; len(s1) <> len(s2) ===
    220,231 ns : UCase(s1) = UCase(s2)
    207,072 ns : s1.ToUpper = s2.ToUpper
    110,625 ns : UCase(s1) = s2
    90,745 ns : String.Compare(s1, s2, True) = 0
    4,434 ns : String.Equals(s1, s2, StringComparison.OrdinalIgnoreCase)

    === APPELS BYVAL BYREF - VALEURS DANS CALL ===
    0,773 ns : Call Sub1(A As Integer, B As Double, C As String)
    0,555 ns : Call Sub2(ByVal A As Integer, ByVal B As Double, ByVal C As String)
    0,553 ns : Call Sub3(ByRef A As Integer, ByRef B As Double, ByRef C As String)
    0,556 ns : Call Sub4(ByVal A As Integer, ByVal B As Double, ByRef C As String)

    === APPELS BYVAL BYREF - VARIABLES ===
    0,669 ns : Call Sub1(A As Integer, B As Double, C As String)
    0,559 ns : Call Sub2(ByVal A As Integer, ByVal B As Double, ByVal C As String)
    0,565 ns : Call Sub3(ByRef A As Integer, ByRef B As Double, ByRef C As String)
    0,562 ns : Call Sub4(ByVal A As Integer, ByVal B As Double, ByRef C As String)

    === COLLECTION VS LIST(OF ) / FOR EACH ===
    207,673 ns : Collection - Construction et For Each
    109,098 ns : List(Of ) - Construction et For Each

    === COLLECTION VS LIST(OF ) / .ITEM(I) ===
    19558,783 ns : Collection - Construction et For i
    12,548 ns : List(Of ) - Construction et For i

    === LIST(OF ) : FOR EACH / FOR I .ITEM(I) ===
    5,449 ns : For Each
    1,896 ns : For i

    === FONCTIONS MATHÉMATIQUES ===
    0,783 ns : +
    0,783 ns : -
    0,718 ns : *
    5,659 ns : /
    5,305 ns : SQRT
    26,837 ns : SIN
    31,252 ns : COS
    38,753 ns : TAN
    24,131 ns : LOG
    20,959 ns : ASIN
    23,106 ns : ACOS
    43,640 ns : ATAN

    === OPÉRATEURS += ===
    1,135 ns : x = x + 1
    0,828 ns : x += 1

    === OPÉRATEURS -= ===
    1,156 ns : x = x - 1
    0,831 ns : x -= 1

    === OPÉRATEURS /= ===
    0,940 ns : x = x / 3
    0,558 ns : x /= 3

    === OPÉRATEURS *= ===
    1,545 ns : x = x * 3
    1,157 ns : x *= 3

    === / CTE VS * CTE ===
    0,780 ns : z = x / 2
    0,551 ns : z = x * 0.5

    === / VAR VS * VAR ===
    0,679 ns : z = x / y
    0,551 ns : z = x * y

    === / VAR VS * VAR II ===
    6,677 ns : zi = xi / y avec y = i
    2,042 ns : zi = xi * y avec y = 1/i

    A+
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  11. #11
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 192
    Points : 28 073
    Points
    28 073
    Par défaut
    Citation Envoyé par electroremy Voir le message
    Je mesure le temps avec monStopWatch.ElapsedMilliseconds ; donc c'est pas bon ?
    Bon, oui, en gardant à l'esprit que la mesure a une marge d'erreur de +/-20ms
    (18,2ms pour être exact mais même Microsoft communique de moins en moins sur l'exactitude de cette valeur et indique souvant 20ms environ)

    C'est un peu comme les sondages d'élections, un tel est devant avec 0.2% d'avance mais 0,2% à +/-0,5.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  12. #12
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 192
    Points : 28 073
    Points
    28 073
    Par défaut
    Bon, en vérifiant les 2 jeux de résultats et en constatant que les premiers étaient tout de même relativement juste notamment sur les faibles valeurs, j'ai eu un petit doute.


    Que MSDN m'a confirmé :
    Stopwatch mesure le temps écoulé en comptant les graduations de la minuterie dans le mécanisme de minuterie sous-jacent. Si le matériel et le système d'exploitation installés prennent en charge un compteur de performance haute résolution, la classe Stopwatch utilise ce compteur pour mesurer le temps écoulé. Sinon, la classe Stopwatch utilise l'horloge système pour mesurer le temps écoulé. Utilisez les champs Frequency et IsHighResolution pour déterminer la précision et la résolution de l'implémentation du minutage Stopwatch.
    Donc, lorsque le matériel en est capable, StopWatch utilise les QueryPerformanceCounter et fait donc des mesures les plus précises possibles
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  13. #13
    Inactif  

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2012
    Messages
    4 904
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4 904
    Points : 10 168
    Points
    10 168
    Billets dans le blog
    36
    Par défaut
    Bonjour,

    Je ne sais pas s'il est disponible en français, mais dans Code Complete, chez Microsoft Press, Steve McConnel, raconte quelques histoires d'optimisations qu'il a lui-même vécues ou connues.

    À un certain moment, il a tellement optimisé un programme qu'il en est devenu illisible. Ou encore, la fois où un programme (non .net) a été optimisé avec un compilateur donné. Sur un autre compilateur, le même programme "optimisé" était plus lent que sa version non-optimisée.

    Sans être un expert de l'optimisation, ni de la plate-forme .net elle-même; donc, c'est possible que je dise une ânerie une ânerie, je me demande des fois si la plate-forme .net ne devient pas un frein à l'optimisation à outrance; ne serait-ce que par l'obligation faite au compilateur VB (ou C# ou ...) de produire un code compatible avec le CLR.

    Et puis, ce cher Windows qui peut faire décoller une recherche de virus sans se poser de question, au moment même où un programme exécute une opération importante ou délicate, n'est pas toujours d'une grande aide dans l'exécution "optimale".

    Et puis, avec tous ces hackers gens qui ajoutent toutes sortes de patentes et de services inutiles comme la mise à jour automatique d'un programme qu'ils mettent à jour une fois par année ou de tests de la "santé de la machine", à un logiciel de désinstallation de programmes.

    Finalement, je me dis que les contraintes "externes" sont tellement imprévisibles ou impossibles à contrer complètement, que l'optimisation est probablement une cause perdue ou presque. Mais, je me trompe peut-être et ce ne serait pas la première fois.
    À ma connaissance, le seul personnage qui a été diagnostiqué comme étant allergique au mot effort. c'est Gaston Lagaffe.

    Ô Saint Excel, Grand Dieu de l'Inutile.

    Excel n'a jamais été, n'est pas et ne sera jamais un SGBD, c'est pour cela que Excel s'appelle Excel et ne s'appelle pas Access junior.

  14. #14
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 192
    Points : 28 073
    Points
    28 073
    Par défaut
    Il faut savoir raison gardée. L'optimisation à outrance est l'ennemie juré de la maintenance et de l'évolution d'un code, non seulement parce qu'un code trop optimisé devient effectivement illisible et est difficilement reprenable, mais surtout parce que l'optimisation extrême consomme énormément de ressource développeur et qu'à chaque modification, il faut recommencer.

    L'optimisation extrême était valable il y a 25 ans ou les performances du matériel étaient plus que limitées. De nos jours, elles ne se justifient que sur de très rares projets très sensibles.
    La plupart des logiciels même les plus gourmands ne savent que faire de toute la débauche de puissance de nos machines actuelles. Les piètres performances, actuellement, viennent plus d'un mauvais code que d'une absence d'optimisation.

    Autre point, l'optimisation poussée est une technique qui n'est pas à la portée de tout développeur, les spécialistes sont rare et coutent cher. L'optimisation que peut faire un développeur lambda maintenant, généralement les compilateurs modernes font d'eux-même aussi bien voire mieux.
    D'ailleurs plus que d'optimisation, il vaudrait mieux parler de bonne pratiques de codage actuellement.

    Pour ce qui est des langages, pour de l'optimisation extrême, il n'y en a qu'un seul qui le permet vraiment, c'est l'assembleur. Le C, étant très bas niveau, permet aussi de s'en rapprocher sérieusement.

    Pour ce qui est des langages .Net (ou Java, c'est le même principe), on est évidemment limité par le fonctionnement de la CLR (VM pour Java). L'optimisation que l'on peut faire, n'est pas de l'optimisation, mais de la bonne pratique de codage pour éviter d'embrouiller le compilateur et lui faciliter la tache parce qu'on final c'est lui qui optimise et pas le développeur.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  15. #15
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Il faut savoir raison gardée. L'optimisation à outrance est l'ennemie juré de la maintenance et de l'évolution d'un code, non seulement parce qu'un code trop optimisé devient effectivement illisible et est difficilement reprenable, mais surtout parce que l'optimisation extrême consomme énormément de ressource développeur et qu'à chaque modification, il faut recommencer.
    Oui !

    Citation Envoyé par sevyc64 Voir le message
    L'optimisation extrême était valable il y a 25 ans ou les performances du matériel étaient plus que limitées. De nos jours, elles ne se justifient que sur de très rares projets très sensibles.
    La plupart des logiciels même les plus gourmands ne savent que faire de toute la débauche de puissance de nos machines actuelles.
    Je suis mitigé la dessus, pour deux raisons :
    - il est frustrant de voir des machines de plus en plus performantes mais des programmes de plus en plus lents; ou plutôt, la performance perçue n'augmente pas aussi vite que celle du hardware
    - les ordinateurs et Internet consomment de plus en plus d'énergie au niveau mondial ; optimiser c'est consommer moins de ressources CPU, donc consommer moins d'énergie et aussi offrir la possibilité aux utilisateurs de continuer à utiliser un PC un peu ancien quelques années (ou quelques mois) de plus. L’obsolescence programmée c'est pas cool, n'y contribuons pas

    Je fais de l'informatique depuis 1993, je n'ai eu que 4 ordinateurs (Amiga 1200, Cyrix 166+, Athlon XP 1600+, et enfin mon actuel qui est un Intel 8 coeurs). Durant la même période quelques uns de mes amis ont eu plus de 12 ordinateurs !

    Citation Envoyé par sevyc64 Voir le message
    Les piètres performances, actuellement, viennent plus d'un mauvais code que d'une absence d'optimisation.
    Oui et re-oui ! il faut d'abord optimiser les équations mathématique du programme et son algorithme

    Citation Envoyé par sevyc64 Voir le message
    Pour ce qui est des langages, pour de l'optimisation extrême, il n'y en a qu'un seul qui le permet vraiment, c'est l'assembleur. Le C, étant très bas niveau, permet aussi de s'en rapprocher sérieusement.
    Mais adieu la portabilité :-P

    A l'école on avait optimisé un logiciel à fond mais il ne pouvait fonctionner que sur un ordinateur : celui qui avait servit à programmer le logiciel

    Citation Envoyé par sevyc64 Voir le message
    Pour ce qui est des langages .Net (ou Java, c'est le même principe), on est évidemment limité par le fonctionnement de la CLR (VM pour Java). L'optimisation que l'on peut faire, n'est pas de l'optimisation, mais de la bonne pratique de codage pour éviter d'embrouiller le compilateur et lui faciliter la tache parce qu'on final c'est lui qui optimise et pas le développeur.
    Tu as trouvé ce que je voulais faire en fait : de la bonne pratique de codage - Exemple : utiliser List(Of ) au lieu de Collection permet un gain de performance important dans mes programmes et le code reste lisible

    De même, utiliser Strings.Equals au lieu de l'opérateur = est beaucoup plus rapide et le code reste lisible. En fait, le code est même plus lisible car l'opérateur "=" en VB.NET est ambigu : il devrait y avoir un "==" comme en C++ distinct du "=" d'affectation ; de plus, un "=" de comparaison peut être confondu avec un "Is" quand on est fatigué.

    Tout ceci est fort instructif, je suis assez content :-)

    Avez-vous d'autres idées de tests ? Je pense faire les benchs suivants :
    - de fonction de lecture et d'écriture de fichiers
    - du gain apporté par les blocs With... End With
    - du gain apporté par le remplacement de fonctions par du code "inline" (d'ailleurs dommage que inline n'existe pas en VB.NET)

    PS : n’hésitez pas à télécharger le zip pour regarder mon programme de bench... il y a peut être une grosse erreur dedans
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  16. #16
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par electroremy Voir le message
    J'ai fait un benchmark maison et les résultats sont très instructifs.
    A mes yeux les résultats sont surtout très prévisibles.

    Par exemple il n'est pas étonnant que vérifier la longueur de la chaîne (un champ à lire) soit plus rapide que comparer un à un deux chaînes de caractères (au moins deux champs à lire avec une chaîne vide, peut-être quatre ou six, avec en plus une comparaison par référence au début). Du coup il serait peut-être davantage bénéfique pour toi d'examiner les sources de la bibliothèque dotnet ou d'approfondir tes connaissances sur la façon dont ces langages sont exécutés par le processeur. Voire de faire un peu d'assembleur, d'autant que c'est amusant.


    Au passage choisir entre multiplication et division est rarement significatif. Dans des programmes réels cela peut même ne faire aucune différence. Si tu veux vraiment optimiser tu as trois pistes :
    * Utiliser de meilleurs algorithmes et structures de données. En particulier chercher un moyen pour faire moins de traitements (calculs incrémentaux, mémoisation, etc).

    * Optimiser l'agencement de la mémoire. En effet les programmes sont bien souvent dominés par les temps d'accès à la mémoire car durant le temps qu'il faut pour lire une seule ligne depuis la RAM (64 octets - 16 Int32) le CPU peut exécuter 400 additions ! Une part essentielle de l'optimisation consiste donc à organiser tes données en mémoire de telle façon que tout tienne en cache et que les accès soient séquentiels. Pour cela tu peux remplacer tes classes par des structures dans un tableau, scinder certains types en plusieurs autres selon le moment où chaque donnée est utilisée (par exemple les jeux séparent les composantes des sommets en plusieurs tableaux : un tableau pour les positions, un tableau pour les normales, un tableau pour les coordonnées textures, etc), t'efforcer d'avoir un code séquentiel (donc pas d'appel virtuel), etc. Un billet sur le sujet et un site plus poussé.

    * La parallélisation. Aujourd'hui les CPU ont six à huit coeurs, demain ce seront douze à seize, puis encore davantage. Se pencher sur des micro-optimisations tout en n'utilisant qu'un seul thread serait absurde. Et le calcul sur GPU est aussi une très bonne piste pour les problèmes qui s'y prêtent (y compris ceux qui ne s'y prêtent pas parfaitement ! Les GPU ne sont plus aussi manchots avec les branchements conditionnels).


    Ces pistes peuvent te permettre de réduire très significativement les temps d'exécution. Bien plus que ton approche (sans doute fausse par ailleurs, voir ci-dessous).

    Je mesure le temps avec monStopWatch.ElapsedMilliseconds ; donc c'est pas bon ?
    C'est le bon choix. Par contre as-tu pensé à faire un "tour de chauffe" (warm-up) ? C'est à dire à exécuter une première fois le code avant de lancer le benhcmark, pour être sûr que le JIT a déjà compilé cette méthode ? Ça expliquerait certains résultats étranges où la première mesure est toujours un peu plus longue qu'elle ne le devrait, sans doute parce qu'elle inclut la durée de la compilation JIT.


    oui c’est pour ça que j’ai fait ce bench, car les applis sur lequels je bosse possèdent des fonctions gourmandes en calcul
    Le message très important qu'il a cherché à te faire passer c'est qu'on n'optimise pas une application en saupoudrant quelques astuces un peu partout. On l'optimise en identifiant d'abord très précisément les parties qui sont lentes et quelles opérations sont en cause. Une fois que c'est fait tu t'attaques à ce point précis.

    En somme : utilise un profileur.

    Citation Envoyé par sevyc64 Voir le message
    - les appels de fonctions : Je ne comprend pas la différence de temps entre les call sub1 et call sub2, les 2 étant strictement identique (les byval sont implicite dans le call sub1, le compilateur agit comme s'ils y étaient)
    - le second point c'est les temps à 200 voire 400ms sur des instructions pour tant relativement simples
    a) Je parie sur l'absence de tour de chauffe, comme je viens de l'expliquer juste au-dessus.

    b) Ces temps sont évidemment pour des itérations très nombreuses. En pratique une division ne prend environ qu'une nanoseconde de nos jours, et un appel de méthode quelques nanosecondes. En-dessous de la centaine de millions d'instructions par seconde ton CPU bronche à peine. Et tu peux aller bien au-delà.


    Citation Envoyé par sevyc64 Voir le message
    Bon, oui, en gardant à l'esprit que la mesure a une marge d'erreur de +/-20ms
    (18,2ms pour être exact mais même Microsoft communique de moins en moins sur l'exactitude de cette valeur et indique souvant 20ms environ)

    C'est un peu comme les sondages d'élections, un tel est devant avec 0.2% d'avance mais 0,2% à +/-0,5.
    15,6 ms en fait (1/60ème de seconde) mais ce n'est que la valeur par défaut. Il est possible de démarrer windows en réclamant une horloge plus précise et, par ailleurs, dès lors qu'une application dans le système instancie un timer multimédia l'horloge du système passe, il me semble, à 100µs, ce qui affecte toutes les applications. Ce qui explique que certains jeux soient soudains plus fluides en ouvrant un lecteur vidéo en arrière-plan.


    Citation Envoyé par sevyc64 Voir le message
    La plupart des logiciels même les plus gourmands ne savent que faire de toute la débauche de puissance de nos machines actuelles.
    Ah ça non !

    Que tu dises que la plupart des logiciels n'ont plus besoin d'optimiser, oui, tout à fait. Mais crois bien que nombre d'applications adoreraient avoir des CPU cent fois plus puissants. Et à ce niveau ce serait encore loin d'être une débauche de puissance dont on ne saurait que faire ! Outils de développement (compilateurs "intelligents"), reconnaissance, minage et synthèse, raytracing et physique pour le JV, et bien d'autres encore.

    La stagnation de la puissance CPU et la lenteur de la parallélisation sont de gros problèmes et cela va être une belle opportunité pour certains services dans le nuage qui pourront offrir des prestations qu'aucune machine cliente ne pourra offrir. Et j'ajoute que pour produire des logiciels toujours plus complexes à main d’œuvre constante il faudra avoir des abstractions de plus en plus hautes et gourmandes. Pendant ce temps la puissance séquentielle des CPU stagne ou presque depuis dix ans. A vrai dire je pense que nous aurons besoin de langages plus expressifs et mieux optimisables.

    Pour ce qui est des langages, pour de l'optimisation extrême, il n'y en a qu'un seul qui le permet vraiment, c'est l'assembleur. Le C, étant très bas niveau, permet aussi de s'en rapprocher sérieusement.
    Non, on n'optimise pas en écrivant son programme en assembleur ! Pas en 2015. On optimise en utilisant des algorithmes plus complexes mais optimaux, en réagençant ses données, en parallélisant, etc. Si tu places trois boucles vectorielles en assembleur ce sera déjà bien et ça ne fera pas une grande différence - sauf exception.

    L'optimisation que l'on peut faire, n'est pas de l'optimisation, mais de la bonne pratique de codage pour éviter d'embrouiller le compilateur et lui faciliter la tache parce qu'on final c'est lui qui optimise et pas le développeur.
    Le compilateur dotnet est optimisé pour une compilation rapide et n'optimisera que bien peu ton programme. Tu ne peux pas t'appuyer sur lui. Les compilateurs C/C++ sont quant à eux excellents mais ils opèrent toujours à bas niveau. Ils ne procèderont pas à des changements de haut niveau de l'agencement du code et de ses structures, ne changeront pas ton algorithme, ne paralléliseront pas, etc. Cela demanderait une intelligence du code très basée soit sur une compréhension du domaine métier, soit sur une instrumentation très fine des binaires (profile-guided optimization puissance 10) accompagnée d'une perte de contrôle du développeur.

  17. #17
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    on peut surtout se dire que le compilateur n'est vraiment pas intelligent
    car je ne comprends pas qu'un .length = 0 soit énormément plus rapide qu'un = ""
    quand on teste l'existence de 2 chaines il devrait déjà vérifier si la longueur est la même

    c'est un langage d'assez haut niveau, ca serait dommage de devoir perdre du temps sur des choses si simples


    Citation Envoyé par electroremy Voir le message
    x += 1 et les fonctions similaires sont toutes plus rapides que leur version x = x + 1 ; elles ne sont donc pas codées pareil lors de la compilation
    sur vs 2015 preview je n'ai aucune différence de temps entre les 2 syntaxes
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  18. #18
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    le = prend (peut prendre serait plus correct) en compte la culture ; ça serait surtout une erreur de croire que 2 chaines de longueurs différentes sont forcément différentes. Par exemple le "ß" allemand est égal à un "ss" malgré que leurs longueurs diffèrent. Ce qui montre surtout que comparer les longueurs est certes plus rapide mais ça ne fait pas strictement la même chose que de tester l'égalité de 2 chaines.
    Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
    À quelle heure dormez-vous ?
    Censément, quelqu'un de sensé est censé s'exprimer sensément.

  19. #19
    Membre émérite Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut
    Je dis peut être une bêtise mais je crois que le = "" est plus long car il va d'abord créer une objet string, pour y stocker une chaîne vide...

    Tandis que le Lenght=0 il ne fait qu'un comparaison.

    C'est d'ailleurs aussi pourquoi le StringBuilder est plus rapide que la concaténation avec le &....
    Quand on utilise le &, il va créer autant d'objet string qu'il y a de parties... Ce qu'il ne fait pas avec le string builder.

    C'est aussi pourquoi l'initialisation par String.empty est plus rapide, car il ne créer pas de String.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  20. #20
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    Le runtime maintient un pool des littéraux constants pour éviter ce type de réallocation du coup String.Empty et "" sont (peuvent être) équivalents (vérifiable via ReferenceEquals(String.Empty, "") par exemple)
    Après là où ça se complique c'est selon la version du runtime, l'interning automatique de la chaine vide peut s'appliquer ou pas ; je renvoie à un article d'Eric Lipert pour plus d'infos sur le sujet.
    Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
    À quelle heure dormez-vous ?
    Censément, quelqu'un de sensé est censé s'exprimer sensément.

Discussions similaires

  1. Problème de performance site ASp.Net
    Par LEK dans le forum Développement Web avec .NET
    Réponses: 5
    Dernier message: 23/03/2010, 19h46
  2. Réponses: 1
    Dernier message: 05/02/2008, 15h35
  3. Performance et ASP.NET / comparaison java ?
    Par tefirette dans le forum ASP.NET
    Réponses: 3
    Dernier message: 24/09/2007, 13h31
  4. [VB .Net] Performance sur parcours de hashtable
    Par plasticgoat dans le forum Windows Forms
    Réponses: 4
    Dernier message: 07/12/2005, 19h25
  5. [VB.NET] With...End With et performances ?
    Par Dnx dans le forum Windows Forms
    Réponses: 9
    Dernier message: 06/04/2005, 12h37

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