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 :

(VB EXpress 2010 ) Performance : avec Call et sans Call


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut (VB EXpress 2010 ) Performance : avec Call et sans Call
    Bonjour,

    Appel à des experts performance.

    C'est un questionnement que j'ai depuis des années, et qui fait peut-être intervenir des caractéristqiues propres à chaque langage et compilateur.

    Pas vraiment une guerre entre programmation dite spaghetti et programmation structurée ou objet. Quoique ....

    ( et je suis d'une très ancienne école mais très peu expérimenté en VBNet ).

    En VBNet ( 2010 express ) je crée une petite application qui effectue une simple opération d'incrémentation d'un nombre CC dans une boucle.
    Le premier test se fait avec le calcul dans la boucle, l'autre avec le calcul dans un call.

    Les résultats sont éloquents ( dans mon test ).

    Est ce moi qui utilise très mal l'art de programmer en VBNet? Y a t il des optimisations à la compilation que je n'ai pas vues?

    Je sais que je peux faire de multiples appels à ma procédure depuis différents endroits dans mon programme, et que je ne dois donc pas répéter le code. Que cela facilite la maintenance ...
    mais quand même, la performance peut être cruciale dans certains cas.

    Cette performance est d'ailleurs importante dans une application que je construis.

    Boucle avec Call 18 secondes
    Boucle sans Call 5 secondes


    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
    Private Sub BCallWith_Click(sender As System.Object, e As System.EventArgs) Handles BCallWith.Click
            debuts = Now
            CC = 0
            For i = 1 To 2000000000
                Call Pr_Call()
            Next
            debute = Now
            dureet = DateDiff(DateInterval.Second, debuts, debute)
            TBDur.Text = dureet
            TBCC.Text = CC
        End Sub
     
     
        Private Sub Pr_Call()
            CC = CC + 1
        End Sub
     
        Private Sub BCallWithout_Click(sender As System.Object, e As System.EventArgs) Handles BCallWithout.Click
            debuts = Now
            CC = 0
            For I = 1 To 2000000000
                CC = CC + 1
            Next
            debute = Now
            dureet = DateDiff(DateInterval.Second, debuts, debute)
            TBDur.Text = dureet
            TBCC.Text = CC
        End Sub
    Et puis patatra, tout ce que je dis ne tient plus !!!! Je teste toutes facettes et me rends compte que si j'exécute d'abord "sans call" puis "avec call", les résultats s'inversent.
    Nouveau démarrage de l'application.

    Boucle sans Call 21 secondes
    Boucle avec Call 12 secondes


    Je redémarre encore une fois dans l'ordre Avec puis Sans.

    Boucle avec Call 18 secondes
    Boucle sans Call 5 secondes


    Totalement perdu. Où est la logique?( Peut-être pas chez moi )
    Y a t il un endroit où je pourrais trouver des conseils, des règles de performance?

    Quelques commentaires sur ceci ( en espérant avoir bien expliqué ).

    Grand merci.

    Pierre

  2. #2
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Bonjour, je te propose de refaire tes essais avec mon code.
    Le travail fait par ta Pr_Call n'est pas le même que celui fait dans ta boucle sans le call.
    En effet, sans le call, tu calcules cc = cc + 1, avec les valeurs de cc variant de 0 à 2000000000.
    Tandis que dans le Pr_Call, tu calcules cc = cc + 1, avec les valeurs de cc variant de 0 à 1, car ta variable est réinitialisée à chaque appel. Certes, cela ne doit pas changer grand chose mais tant qu'à pinailler ...
    Pour que le travail dans Pr_Call soit le calcul de cc = cc + 1, avec les valeurs de cc variant de 0 à 2000000000, il faut déclarer la variable cc static dans Pr_Call.
    A propos de déclarer, il convient de déclarer toutes les variables en VB.Net (comme en Fortran, ou en Cobol, dans l'ancien temps ... .
    Je me suis permis de retravailler ton code et je te le mets ci-dessous.
    C’est "infiniment plus long" avec le call et c'est bien normal vu l'important nombre de branchements demandés, ce sont autant de JUMP à accomplir par le processeur dans la mémoire du code, dans le code segment.
    Note au passage, que si l'instruction Call a encore son rôle à jouer dans des scripts Dos et danns quelques cas en VBA, elle est absolument superflue en VB.Net : Call UneProcedure() est équivalent à UneProcedure().
    Voici le code :
    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
        Private Sub BCall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BCall.Click
            Dim debuts As Date = Now
            Dim fins As Date
            Dim CC As Long = 0
            Dim Max As Long = 2000000000
            For i As Long = 1 To Max
                Call Pr_Call()
            Next
            fins = Now
            TDuree.Text = DateDiff(DateInterval.Second, debuts, fins)
        End Sub
     
        Private Sub Pr_Call()
            Static CC As Long = 0
            CC = CC + 1
        End Sub
     
        Private Sub BNoCall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BNoCall.Click
            Dim debuts As Date = Now
            Dim fins As Date
            Dim CC As Long = 0
            Dim Max As Long = 2000000000
            For i As Long = 1 To Max
                CC = CC + 1
            Next
            fins = Now
            TDuree.Text = DateDiff(DateInterval.Second, debuts, fins)
        End Sub
    End Class
    Cordialement ...

  3. #3
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut
    merci pour la réponse et les indications

    Je planche un peu là-dessus et reviens un plus tard.

    Bonne soirée

    Pierre

  4. #4
    Membre éprouvé Avatar de excalybur
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2014
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2014
    Messages : 317
    Par défaut
    Une autre solution serait d'ajouter des temporisations :
    Thread.Sleep(18000)pour 18 secondes.

  5. #5
    Membre confirmé
    Homme Profil pro
    Tooling - Testing
    Inscrit en
    Décembre 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : Belgique

    Informations professionnelles :
    Activité : Tooling - Testing

    Informations forums :
    Inscription : Décembre 2008
    Messages : 141
    Par défaut
    Excalybur,

    merci !! pour la remarque, mais euh !! je ne veux pas temporiser, mais aller le plus rapidement possible. Dans mon exemple, je comparais deux méthodes qui me donnaient des résultats différents en temps.

    J'ai dû mal m'expliquer. Sorry.

    Bonsoir.

    Pierre

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    normalement un appel de méthode prend du temps, donc ne pas le mettre devrait en gagner
    après ce temps c'est en pico ou nano seconde, donc c'est utile d'inliner quand il y a beaucoup voir énormément d'appels à cette méthode dans une boucle
    et c'est utile d'avoir une méthode quand ca apporte de la clarté dans le code

    après concernant la mesure du temps, pour mesurer un temps on utilise system.diagnostics.stopwatch qui sera plus précis (c'est un chrono avec .Start .Stop .ElapsedMilliseconds)

    concernant le test d'exécution il convient de connaitre les mécanismes de .net (hors .net core qui est différent)
    un code .net est compilé en MSIL dans l'exe, c'est un langage intermédiaire
    à chaque exécution de l'exe celui ci est compilé en code natif, mais au fur et à mesure de l'exécution
    donc l'appel d'une méthode a des chances d'être plus long au premier appel qu'aux autres
    il faut donc tester plusieurs fois chaque méthode pendant la même exécution

    autre chose, il y a une différence entre le code que tu écris et le code compilé, .net peut de lui même décider de mettre le code d'une méthode dans une autre pour justement éviter d'avoir le temps d'appel
    ca arrive surtout sur des méthodes petites (ton cas)
    il est possible d'essayer d'influencer le compilateur avec des attributs


    concernant l'optimisation, connaitre certaines choses permet d'écrire directement du code performant
    sinon il faut attendre d'avoir quelque chose à optimiser avant de l'optimiser, si un truc est appelé 1 fois par heure et qu'il prend 50 ms ca serait pas forcément important d'essayer de l'optimiser, alors qu'un truc appelé 10x par seconde mettant 20ms là tu jette un œil pour voir si tu peux l'améliorer
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

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

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