begin process at 2010 03 20 12:39:59
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Optimisation du code

 > TUTORIEL OPTIMISATIONS AVANCÉES

TUTORIEL OPTIMISATIONS AVANCÉES


 Information sur la source

Note :
9,85 / 10 - par 13 personnes
9,85 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Optimisation du code Niveau :Initié Date de création :11/08/2003 Date de mise à jour :11/08/2003 20:43:37 Vu :15 169

Auteur : Proger

Ecrire un message privé
Site perso
Commentaire sur cette source (28)
Ajouter un commentaire et/ou une note

 Description

Voici une liste de modification de codes pour optimiser vos applications. Présenté sous forme de "avant-après", ces optimisations sont pour ceux qui recherche la performance et non pas la lisibilité!! (quitte à casser les conventions...)

Attention, n'oubliez jamais qu'un code compilé sera toujours plus rapide qu'un code interprété.


Les optimisations présentées ci-dessous sont des échantillons, à adapté dans vos situations/algos
  

Source

  • 'OptCode
  • 'tuto pour les fous
  • 'Ces optimisations sont sensible lorsque le code est compilé.
  • 'Il est probable qu'en mode interprété, les "Après" soit plus lent que "Avant"
  • 'Pas de copyright (et puis quoi encore ! :p )
  • ' ====== DEFS ======
  • DefLng A-Z
  • 'DefType : Au lieu de faire Dim i As Long, j As Long, ...
  • '... il suffra de faire Dim i, j
  • Option Base 1
  • 'ReDim MonTablo(1 to MaVal) pourra être écrit ...
  • 'ReDim MonTablo(MaVal)
  • Option Explicit
  • 'Obligation de faire des "Dim" pour chaque variable ...
  • 'Evitant ainsi d'utiliser le type Variant, très lent!
  • Option Compare Binary
  • 'La Comparaison binaire est la plus rapide.
  • 'S'utilise avec InStr(), InStrRev(), Replace() ...
  • Option Private Module
  • 'Tout les subs, functions et declares sont sous-entendu "Private"
  • ' ====== TESTS ======
  • 'Avant
  • If b = 27 Then
  • a = True
  • Else
  • a = False
  • End If
  • 'Après
  • Dim a As Boolean
  • a = (b = 27)
  • 'Avant
  • If b = 27 And g < 50 Or (c * b > 250) Then
  • a = True
  • Else
  • a = False
  • End If
  • 'Après
  • Dim a As Boolean
  • a = (b = 27 And g < 50 Or (c * b > 250))
  • 'Avant
  • If b >= 0 And b < 255 Then
  • a = 32767
  • End If
  • 'Après (à utilisé avec précaution)
  • If (b And 255) = b Then
  • a = 32767
  • End If
  • 'Avant
  • For i = 1 To 5000
  • If i > 4000 Then
  • a = a + 2
  • Else
  • a = a + 1
  • End If
  • Next i
  • 'Après (le test qui sera "True" le plus souvent dois être le premier, si possible)
  • For i = 1 To 5000
  • If i <= 4000 Then
  • a = a + 1
  • Else
  • a = a + 2
  • End If
  • Next i
  • 'RAPPEL :
  • ' - au niveau assembleur, les opérations booléennes se font en 1 instruction
  • ' c'est donc très rapide, plus rapide que les tests.
  • ' Mais pour profiter de cette rapidité, il faut compiler le programme!
  • ' - l'instruction GOTO est très performante, converti en assembleur!
  • ' ====== TEXTES ======
  • 'Avant
  • g$ = Left(Trim(Str$))
  • 'Après
  • Dim g As String
  • g = Left$(Trim$(Str$))
  • 'Avant
  • For i = 1 To 100
  • txt$ = txt$ & "toto"
  • Next i
  • 'Après (si on connais la longeur finale de txt$)
  • txt$ = Space$(Len("toto") * 100)
  • For i = 1 To 400 Step 4
  • Mid$(txt$, i, 4) = "toto"
  • Next i
  • 'Avant
  • t = InStr(1, g$, "toto", vbTextCompare)
  • 'Après
  • t = InStr(1, g$, "toto", vbBinaryCompare)
  • 'Encore Après
  • Option Compare Binary
  • Dim t As Long
  • t = InStr(1, g$, "toto", -1) 'vbUseCompareOption
  • 'RAPPEL :
  • ' - certaines fonctions de manipulation de chaine existe en mode binaire.
  • ' LeftB(), RightB(), MidB(), InStrB()
  • ' Sachant que les chaines String$ sont sur 2 octets (unicode), cela peut
  • ' être utile lorsque on manipule la mémoire via pointeur plutôt que la
  • ' valeur... (comprenne qui pourra!)
  • ' - Avant de coder une fonction de manipulation de chaine, vérifiez qu'elle
  • ' n'existe pas déjà!
  • ' Space$(),String$(),Trim$(),LTrim$(),RTrim$(),LSet,Rset
  • ' StrComp(),InStrRev(),Replace(),Split(),Filter(),StrConv(),StrReverse()
  • ' ====== OBJETS ======
  • 'Avant
  • Dim Bvv As New MaClasseQueJaiFait
  • Bvv.Init
  • Bvv.Param1 = 254
  • Bvv.Param2 = "toto"
  • 'Après
  • Dim Bvv As New MaClasseQueJaiFait
  • With Bvv
  • .Init
  • .Param1 = 254
  • .Param2 = "toto"
  • End With
  • 'Avant
  • For i = 1 To Len(Text1.Text)
  • g$ = g$ & Mid$(Text1.Text, i, Len(Text1.Text) - i + 1)
  • Next i
  • 'Après (version 1)
  • Dim i As Long, l As Long, tx1 As String
  • tx1 = Text1.Text
  • l = Len(tx1)
  • For i = 1 To l
  • g$ = g$ & Mid$(tx1, i, l - i + 1)
  • Next i
  • 'Après (version 2)
  • Dim i As Long
  • With Text1
  • For i = 1 To Len(.Text)
  • g$ = g$ & Mid$(.Text, i, Len(.Text) - i + 1)
  • Next i
  • End With
  • 'Avant
  • Dim MaCollection() As MaClasseTruc
  • '[...]
  • For i = 1 To UBound(MaCollection())
  • MaCollection(i).Truc = Machin
  • MaCollection(i).FonctionBidule Param1
  • If MaCollection(i).Tata = True Or MaCollection(i).Titi = True Then
  • MaCollection(i).VazyGo
  • End If
  • Next i
  • 'Après
  • Dim MaCollection() As MaClasseTruc
  • '[...]
  • For i = 1 To UBound(MaCollection())
  • With MaCollection(i)
  • .Truc = Machin
  • .FonctionBidule Param1
  • If .Tata = True Or .Titi = True Then
  • .VazyGo
  • End If
  • End With
  • Next i
  • 'Avant
  • Dim Momo As MaClasseIci
  • Dim Mimi As MaClasseParam
  • '[...]
  • If Momo.Totoz(Mimi.Valeur(Index1)) = 1 Then
  • Call FonctionQuiGere(Momo.Totoz(Mimi.Valeur(Index1)))
  • End If
  • 'Après
  • Dim Momo As MaClasseIci
  • Dim Mimi As MaClasseParam
  • '[...]
  • Dim MaVal As Long
  • MaVal = Momo.Totoz(Mimi.Valeur(Index1))
  • If MaVal = 1 Then
  • Call FonctionQuiGere(MaVal)
  • End If
  • ' RAPPEL :
  • ' - appeler une variable ou une fonction d'un objet oblige a appelé
  • ' un gestionnaire d'objets (c'est lent)
  • ' - mieux vaux utiliser un maximum de modules / un minimum d'objets
  • ' ou encore un objet avec beaucoup de fonctions Private, le rendant autonome
  • ' - les OCX sont des objets encore plus lent que des classes, car externe au projet.
  • ' - DirectX et ses affiliés sont des objets, et s'optimise très bien avec ces astuces.
  • ' ====== ALGOS DIVERS ======
  • Sub DecomposeRGB(Couleur As Long)
  • 'Avant (maths)
  • cb = Int(Couleur / 65536)
  • cg = Int((Couleur - cb * 65536) / 256)
  • cr = Couleur - cg * 256 - cb * 65536
  • 'Après (bitmask)
  • cb = Couleur And 255&
  • cg = (Couleur And &HFF00&) / 256&
  • cr = (Couleur And &HFF0000) / &H10000
  • End Sub
  • 'Avant
  • For i = 1 To 150000
  • Next i
  • 'Après (vitesse a vérifier en benchmark post-compilatoire : varie selon l'algo)
  • Dim i As Long
  • i = 1
  • Do While i <= 150000
  • i = i + 1
  • Loop
  • ' nota : très utile lorsque vous devez imbriquer des boucles.
  • 'Avant
  • Sub Wait(Duree As Single)
  • t1 = Timer + Duree
  • Do While Timer < t1
  • Loop
  • End Sub
  • 'Après (selon besoins de préçision)
  • Declare Sub Sleep Lib "kernel32" (ByVal DureeMS As Long)
  • Sub Wait2(Duree As Single)
  • Dim t1 As Single
  • t1 = Timer + Duree
  • Do While Timer < t1
  • DoEvents '<= evite de bloquer le système
  • Sleep 1& '<= libère le CPU pendant 1 milliseconde (évite de chauffer)
  • Loop
  • End Sub
  • 'Avant
  • For i = 1 To 10000
  • t = t + i * Sqr(5)
  • Next i
  • 'Après (précalcul)
  • sq = Sqr(5)
  • For i = 1 To 10000
  • t = t + i * sq
  • Next i
  • 'Avant (on peut remplacé lbound() par 1 si on connais le plus petit index de la liste)
  • Dim MaListe() As Long
  • Dim MaCopie() As Long
  • '[...]
  • ReDim MaCopie(LBound(MaListe()) To UBound(MaListe()))
  • For i = LBound(MaListe()) To UBound(MaListe())
  • MaCopie(i) = MaListe(i)
  • Next i
  • 'Après (on est pas limité par le type de la destination)
  • Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, ByRef Origine As Any, ByVal Longueur As Long)
  • Dim MaListe() As Long
  • Dim MaCopie() As Long
  • '[...]
  • Dim l As Long
  • l = UBound(MaListe()) - LBound(MaListe()) + 1
  • ReDim MaCopie(1 To l)
  • RtlMoveMemory MaCopie(1), MaListe(LBound(MaListe())), l * 4 '4 octets par entrée
  • 'RAPPEL :
  • ' - Précalculez les valeurs avant les boucles si c'est possible
  • ' - L'utilisation du masque de bits fait parti des astuces de
  • ' programmation impossible a réaliser avec des mathématiques
  • ' - l'API RtlMoveMemorty permet de faire des manipulations de
  • ' données en mémoire, c'est un outil puissant qui fait défaut
  • ' à VB alors qu'il existe dans les autres langages (memcpy en C)
  • ' - la fonction vb VarPtr() couplé à l'API su-cité permet de
  • ' compensé l'absence de pointeur (comme en C)!
  • ' ====== FONCTIONS VB6 PEU UTILISEES ======
  • 'Pour récupérer le dossier temporaire de windows, le dossier système, ...
  • 'peut varié selon l'OS utilisé (win98, win2k, ...)
  • DossierTemp$ = Environ("TMP")
  • DossierTemp$ = Environ("TEMP")
  • ExePathDefault$ = Environ("PATH")
  • DossierWin$ = Environ("WINDIR")
  • 'Connaitre le type d'une variable (débogage)
  • MonType$ = TypeName(MaVar)
  • 'Arrondi au nombre de décimal souhaité
  • MaValInt2 = Round(MaValPrecise, 2)
  • 'Gestion d'erreur
  • 'Classique :
  • Sub MaFunc()
  • On Error Resume Next 'ignore l'erreur
  • End Sub
  • Sub MaFunc2()
  • 'Approfondi :
  • On Error GoTo Gere
  • '[...]
  • Exit Sub
  • Gere:
  • 'gestion
  • Resume 'retourne a la ligne source d'erreur
  • End Sub
  • 'RAPPEL : il vaux mieux faire des tests pour éviter les erreurs plutôt que de laissé On Error gérer l'erreur
  • 'Fonction dans une fonction
  • 'L'interêt est qu'appelé (Call) une fonction est plus lent que faire un GOTO
  • Sub Truc()
  • '[...]
  • GoSub algotemp
  • '[...]
  • Exit Sub
  • algotemp:
  • '[...]
  • Return
  • End Sub
  • 'E/S Fichier
  • 'vous connaissiez :
  • Close
  • 'pour fermer tout les fichiers ouvert ?
  • 'il existe également :
  • Reset
  • 'Qui... fait pareil :)
  • 'Utiliser un masque pour comparer des chaines de caractères
  • b = (MaChaine Like MonMasque)
  • 'autre écriture autorisé :
  • If MaChaine Like MonMasque Then
  • 'démo :
  • MaChaine$ = "pomme": Masque$ = "p?m*"
  • 'alors b = True ...
  • ' ====== ASTUCE ======
  • 'Affichage de l'état / progression d'une fonction
  • 'Avant
  • For i = 1 To 10000
  • Label1.Caption = Format$(i / 100, "#0") & "%"
  • DoEvents
  • Call SubMachin(UnTruc(i))
  • Next i
  • 'Après
  • For i = 1 To 10000
  • If i Mod 100 = 0 Then
  • Label1.Caption = Format$(i / 100, "#0") & "%"
  • DoEvents
  • End If
  • Call SubMachin(UnTruc(i))
  • Next i
  • 'nota : on évite de rafraichir en permanence l'affichage, ce qui gaspille BEAUCOUP de temps-machine
  • 'dans l'exemple "après", on le rafraichit toutes les 100 itérations
'OptCode

'tuto pour les fous

'Ces optimisations sont sensible lorsque le code est compilé.
'Il est probable qu'en mode interprété, les "Après" soit plus lent que "Avant"

'Pas de copyright (et puis quoi encore ! :p )



' ====== DEFS ======

DefLng A-Z
    'DefType : Au lieu de faire Dim i As Long, j As Long, ...
    '... il suffra de faire Dim i, j

Option Base 1
    'ReDim MonTablo(1 to MaVal) pourra être écrit ...
    'ReDim MonTablo(MaVal)
    
Option Explicit
    'Obligation de faire des "Dim" pour chaque variable ...
    'Evitant ainsi d'utiliser le type Variant, très lent!

Option Compare Binary
    'La Comparaison binaire est la plus rapide.
    'S'utilise avec InStr(), InStrRev(), Replace() ...

Option Private Module
    'Tout les subs, functions et declares sont sous-entendu "Private"





' ====== TESTS ======

'Avant
If b = 27 Then
    a = True
Else
    a = False
End If

'Après
Dim a As Boolean
a = (b = 27)




'Avant
If b = 27 And g < 50 Or (c * b > 250) Then
    a = True
Else
    a = False
End If

'Après
Dim a As Boolean
a = (b = 27 And g < 50 Or (c * b > 250))




'Avant
If b >= 0 And b < 255 Then
    a = 32767
End If

'Après (à utilisé avec précaution)
If (b And 255) = b Then
    a = 32767
End If



'Avant
For i = 1 To 5000
    If i > 4000 Then
        a = a + 2
    Else
        a = a + 1
    End If
Next i

'Après (le test qui sera "True" le plus souvent dois être le premier, si possible)
For i = 1 To 5000
    If i <= 4000 Then
        a = a + 1
    Else
        a = a + 2
    End If
Next i


'RAPPEL :
' - au niveau assembleur, les opérations booléennes se font en 1 instruction
'   c'est donc très rapide, plus rapide que les tests.
'   Mais pour profiter de cette rapidité, il faut compiler le programme!
' - l'instruction GOTO est très performante, converti en assembleur!





' ====== TEXTES ======

'Avant
g$ = Left(Trim(Str$))

'Après
Dim g As String
g = Left$(Trim$(Str$))



'Avant
For i = 1 To 100
    txt$ = txt$ & "toto"
Next i

'Après (si on connais la longeur finale de txt$)
txt$ = Space$(Len("toto") * 100)
For i = 1 To 400 Step 4
    Mid$(txt$, i, 4) = "toto"
Next i



'Avant
t = InStr(1, g$, "toto", vbTextCompare)

'Après
t = InStr(1, g$, "toto", vbBinaryCompare)

'Encore Après
Option Compare Binary
Dim t As Long
t = InStr(1, g$, "toto", -1) 'vbUseCompareOption


'RAPPEL :
' - certaines fonctions de manipulation de chaine existe en mode binaire.
'   LeftB(), RightB(), MidB(), InStrB()
'   Sachant que les chaines String$ sont sur 2 octets (unicode), cela peut
'   être utile lorsque on manipule la mémoire via pointeur plutôt que la
'   valeur... (comprenne qui pourra!)
' - Avant de coder une fonction de manipulation de chaine, vérifiez qu'elle
'   n'existe pas déjà!
'   Space$(),String$(),Trim$(),LTrim$(),RTrim$(),LSet,Rset
'   StrComp(),InStrRev(),Replace(),Split(),Filter(),StrConv(),StrReverse()





' ====== OBJETS ======

'Avant
Dim Bvv As New MaClasseQueJaiFait
Bvv.Init
Bvv.Param1 = 254
Bvv.Param2 = "toto"

'Après
Dim Bvv As New MaClasseQueJaiFait
With Bvv
    .Init
    .Param1 = 254
    .Param2 = "toto"
End With



'Avant
For i = 1 To Len(Text1.Text)
    g$ = g$ & Mid$(Text1.Text, i, Len(Text1.Text) - i + 1)
Next i

'Après (version 1)
Dim i As Long, l As Long, tx1 As String
tx1 = Text1.Text
l = Len(tx1)
For i = 1 To l
    g$ = g$ & Mid$(tx1, i, l - i + 1)
Next i

'Après (version 2)
Dim i As Long
With Text1
    For i = 1 To Len(.Text)
        g$ = g$ & Mid$(.Text, i, Len(.Text) - i + 1)
    Next i
End With



'Avant
Dim MaCollection() As MaClasseTruc
'[...]
For i = 1 To UBound(MaCollection())
    MaCollection(i).Truc = Machin
    MaCollection(i).FonctionBidule Param1
    If MaCollection(i).Tata = True Or MaCollection(i).Titi = True Then
        MaCollection(i).VazyGo
    End If
Next i

'Après
Dim MaCollection() As MaClasseTruc
'[...]
For i = 1 To UBound(MaCollection())
    With MaCollection(i)
    .Truc = Machin
    .FonctionBidule Param1
    If .Tata = True Or .Titi = True Then
        .VazyGo
    End If
    End With
Next i



'Avant
Dim Momo As MaClasseIci
Dim Mimi As MaClasseParam
'[...]
If Momo.Totoz(Mimi.Valeur(Index1)) = 1 Then
    Call FonctionQuiGere(Momo.Totoz(Mimi.Valeur(Index1)))
End If

'Après
Dim Momo As MaClasseIci
Dim Mimi As MaClasseParam
'[...]
Dim MaVal As Long
MaVal = Momo.Totoz(Mimi.Valeur(Index1))
If MaVal = 1 Then
    Call FonctionQuiGere(MaVal)
End If


' RAPPEL :
' - appeler une variable ou une fonction d'un objet oblige a appelé
'   un gestionnaire d'objets (c'est lent)
' - mieux vaux utiliser un maximum de modules / un minimum d'objets
'   ou encore un objet avec beaucoup de fonctions Private, le rendant autonome
' - les OCX sont des objets encore plus lent que des classes, car externe au projet.
' - DirectX et ses affiliés sont des objets, et s'optimise très bien avec ces astuces.





' ====== ALGOS DIVERS ======


Sub DecomposeRGB(Couleur As Long)
    'Avant (maths)
    cb = Int(Couleur / 65536)
    cg = Int((Couleur - cb * 65536) / 256)
    cr = Couleur - cg * 256 - cb * 65536

    'Après (bitmask)
    cb = Couleur And 255&
    cg = (Couleur And &HFF00&) / 256&
    cr = (Couleur And &HFF0000) / &H10000
End Sub



'Avant
For i = 1 To 150000

Next i

'Après (vitesse a vérifier en benchmark post-compilatoire : varie selon l'algo)
Dim i As Long
i = 1
Do While i <= 150000

i = i + 1
Loop
' nota : très utile lorsque vous devez imbriquer des boucles.


'Avant
Sub Wait(Duree As Single)
    t1 = Timer + Duree
    Do While Timer < t1
    Loop
End Sub

'Après (selon besoins de préçision)
Declare Sub Sleep Lib "kernel32" (ByVal DureeMS As Long)
Sub Wait2(Duree As Single)
Dim t1 As Single
    t1 = Timer + Duree
    Do While Timer < t1
        DoEvents  '<= evite de bloquer le système
        Sleep 1&  '<= libère le CPU pendant 1 milliseconde (évite de chauffer)
    Loop
End Sub



'Avant
For i = 1 To 10000
    t = t + i * Sqr(5)
Next i

'Après (précalcul)
sq = Sqr(5)
For i = 1 To 10000
    t = t + i * sq
Next i



'Avant (on peut remplacé lbound() par 1 si on connais le plus petit index de la liste)
Dim MaListe() As Long
Dim MaCopie() As Long
'[...]
ReDim MaCopie(LBound(MaListe()) To UBound(MaListe()))
For i = LBound(MaListe()) To UBound(MaListe())
    MaCopie(i) = MaListe(i)
Next i

'Après (on est pas limité par le type de la destination)
Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, ByRef Origine As Any, ByVal Longueur As Long)
Dim MaListe() As Long
Dim MaCopie() As Long
'[...]
Dim l As Long
l = UBound(MaListe()) - LBound(MaListe()) + 1
ReDim MaCopie(1 To l)
RtlMoveMemory MaCopie(1), MaListe(LBound(MaListe())), l * 4  '4 octets par entrée


'RAPPEL :
' - Précalculez les valeurs avant les boucles si c'est possible
' - L'utilisation du masque de bits fait parti des astuces de
'   programmation impossible a réaliser avec des mathématiques
' - l'API RtlMoveMemorty permet de faire des manipulations de
'   données en mémoire, c'est un outil puissant qui fait défaut
'   à VB alors qu'il existe dans les autres langages (memcpy en C)
' - la fonction vb VarPtr() couplé à l'API su-cité permet de
'   compensé l'absence de pointeur (comme en C)!






' ====== FONCTIONS VB6 PEU UTILISEES ======

'Pour récupérer le dossier temporaire de windows, le dossier système, ...
'peut varié selon l'OS utilisé (win98, win2k, ...)
DossierTemp$ = Environ("TMP")
DossierTemp$ = Environ("TEMP")
ExePathDefault$ = Environ("PATH")
DossierWin$ = Environ("WINDIR")



'Connaitre le type d'une variable (débogage)
MonType$ = TypeName(MaVar)



'Arrondi au nombre de décimal souhaité
MaValInt2 = Round(MaValPrecise, 2)



'Gestion d'erreur
'Classique :
Sub MaFunc()
On Error Resume Next 'ignore l'erreur
End Sub

Sub MaFunc2()
'Approfondi :
On Error GoTo Gere
'[...]
Exit Sub
Gere:
    'gestion
Resume 'retourne a la ligne source d'erreur
End Sub

'RAPPEL : il vaux mieux faire des tests pour éviter les erreurs plutôt que de laissé On Error gérer l'erreur



'Fonction dans une fonction
'L'interêt est qu'appelé (Call) une fonction est plus lent que faire un GOTO
Sub Truc()
'[...]
GoSub algotemp
'[...]
Exit Sub
algotemp:
    '[...]
Return
End Sub



'E/S Fichier
'vous connaissiez :
Close
'pour fermer tout les fichiers ouvert ?
'il existe également :
Reset
'Qui... fait pareil :)



'Utiliser un masque pour comparer des chaines de caractères
b = (MaChaine Like MonMasque)
'autre écriture autorisé :
If MaChaine Like MonMasque Then
'démo :
MaChaine$ = "pomme": Masque$ = "p?m*"
'alors b = True ...







' ====== ASTUCE ======

'Affichage de l'état / progression d'une fonction
'Avant
For i = 1 To 10000
    Label1.Caption = Format$(i / 100, "#0") & "%"
    DoEvents
    Call SubMachin(UnTruc(i))
Next i

'Après
For i = 1 To 10000
    If i Mod 100 = 0 Then
        Label1.Caption = Format$(i / 100, "#0") & "%"
        DoEvents
    End If
    Call SubMachin(UnTruc(i))
Next i
'nota : on évite de rafraichir en permanence l'affichage, ce qui gaspille BEAUCOUP de temps-machine
'dans l'exemple "après", on le rafraichit toutes les 100 itérations



 Conclusion

Ces astuces sont presque "obligatoire" si on veux faire des jeux en VB.

Rajoutez vos astuces en commentaire!  


 Sources du même auteur

Source avec Zip Source avec une capture ENREGISTREUR WAVEIN, FILTRE ET ANALYSE SPECTRALE
Source avec Zip Source avec une capture ATTCALC : RENDU D'ATTRACTEURS ETRANGES DE CLIFFORD
Source avec Zip Source avec une capture EXPLORATEUR FRACTALE MANDELBROT HAUTE DEFINITION
TUTORIEL OPTIMISATION AVANCÉES : COMPILATION, COMPILATEUR ET...
Source avec Zip Source avec une capture ANALYSEUR D'EXECUTABLES VB6 (BETA RELEASE)

 Sources de la même categorie

Source avec Zip Source avec une capture ALTERNATIVE À LA FUNCTION VBA OU VB REPLACE (JUSQU'À 10 FOI... par vicosta
Source avec Zip Source avec une capture SIMULATEUR TRIAL VERSION (BASE DE TRAVAIL POUR DÉBUT) par stef68600
Source avec Zip Source avec une capture ÔTER PROTECTION FEUILLE D'UN CLASSEUR EXCEL & TROUVER MOT D... par stef68600
Source .NET (Dotnet) INDIRECTION SUR LES MEMBRES D'UNE CLASSE EN VB.NET OU C#, IN... par GabSoftware
Source avec Zip EXTRACTION DES CHAINES ENTRE GUILEMETS ET CREATION D'UN POIN... par ccgousset

Commentaires et avis

Commentaire de Renfield le 11/08/2003 16:37:43 administrateur CS

bon apercu d'un certain nombre d'ameliorations.
je suis content de voir que je m'en servais deja de la plupart :D

Commentaire de OphidiaN le 11/08/2003 16:38:47

sur le cul... j'en connaissais mais alors là.... merci :)

Commentaire de dragon le 11/08/2003 17:04:36

excellent, rien à redire
bien que pour la plupart, ils sont très connu, il faudrais presque faire un dossier complet sur les optimisation et ici c'est un bon départ

Nix, on demande une nouvelle section sur ton site lol

Commentaire de Bricomix le 11/08/2003 17:33:57

J'ai enregistré cette page comme ça je l'aurai toujours...

10/10

Commentaire de Bricomix le 11/08/2003 17:37:42

Oups j'ai mis 9/10 au lieu de 10/10 mais bon excuse-moi...

Commentaire de NoRabbit le 11/08/2003 19:15:06

très intéressant, je n'en connaissais pas tellement et ce tuto est une très précieuse aide.

n'hésite pas à en remettre, ça m'intéresse fort

Commentaire de JoePatent le 11/08/2003 21:45:13

Il y a de bonnes idées mais il faut être prudent.  L'optimisation se fait au nombre d'opération pas au nombre de ligne de code.
Un code clair et simple est plus facile a modifier et à maintenir.
Exemple simple :
'Avant
If b = 27 Then
    a = True
Else
    a = False
End If

'Après
Dim a As Boolean
a = (b = 27)

Tu ne gagne rien a procéder de la sorte, tu as juste moins de ligne mais aussi moins de clareté.

L'optimisation d'un code source se fait avec une charte mathematique des opérations mathématique effectué par le processeur afin de gagner des cycles...

C'est plus compliqué que simplement changer toute les itérations par de la récursive afin d'avoir moins de lignes...

Bon travail tout de même !

Commentaire de Proger le 11/08/2003 22:06:36

bah, en compilant le prog et en le décompilant en asm, la différence est immédiate. importer une fonction (je parle d'api) est obligatoirement plus lent a exécuté (temps cpu) que de coder soi-même la fonction et de l'appelé avec un simple "jmp near"... l'exemple que tu as choisi répond aussi a cette règle.

Commentaire de shaoni le 12/08/2003 12:31:48

il ya quand meme un truc etonnant c'est que tu preconise l'usage de with
end with avec les objects
alors que un autre test sur ce site prouve la lenteur flagrante de ce procéder !!
ps:faudra que tu explique sur quoi tu te base en desassemblant un exe vb parce que à part l'ordre des call tu passe ton temp dans les fonction de msvbrun !

ceci dit bon boulot quand meme hein !  

Commentaire de Proger le 12/08/2003 13:29:14

En effet, il ne faut pas toujours utilisé With et End With. parfois ça améliore, parfois ça déteriore. En fait, c'est surtout avec directX que tu gagne en performance : utilise .BltFast au lieu de DDS7.BltFast dans une grosse boucle et la différence se ressent immédiatement sur le framerate.

Pour le déasm, aha evidemment je t'attendais au tournant :) . En fait,  tout dépend comment tu compiles. en faisant un code qui utilise essentiellement les instructions de base, et en supprimant tout les contrôles (opt. avancés) on se débarrase de 3/4 des appels à msvbm60. Un __vbaVarForInit et __vbaVarForNext sera remplaçé par un petit jne ... En fait, il serai judicieux de faire un tutoriel sur le compilateur lui-même...

Commentaire de mehdibou le 17/08/2003 19:25:59

Très intéressant, je connaissais la majorité des astuces mais certaines me laissent sceptique (tu as fais des tests pour tous les exemples ?). La plupart des optimisations devraient être effectuées par les compilo...si le compilo de VB était bon.. et apparemment, ce n'est pas le cas.
Tu indique d'utiliser vbCompareBinary car plus rapide, il faut bien sûr préciser que parfois on a besoin d'une comparaison avec vbCompareText.
Les instructions Close et Reset ne sont pas totalement identiques mais la différence est minime.
Dans les fonctions (ou plutot les commandes) peu utilisées, j'ajouterai :
- l'instruction Mid$() dont la syntaxe est particulière puisqu'elle est celle d'un assignement.
- les fonctions IIf(), Choose(), Switch()
Et pour finir, je conseille un article à tous les développeurs vb qui utilisent les chaines de caractères avec les API (paske c vraiment la merde avec leur unicode à la con ; et ça devient encore pire quand on veut interférer avec un autre langage) : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnw32dev/html/ora_apiprog6_topic1.asp

Commentaire de Afyn le 24/01/2004 11:26:54

J'ai fait un test de ce que tu as écrit :

'Avant
For i = 1 To 150000

Next i

'Après (vitesse a vérifier en benchmark post-compilatoire : varie selon l'algo)
Dim i As Long
i = 1
Do While i &lt;= 150000

i = i + 1
Loop
' nota : très utile lorsque vous devez imbriquer des boucles.

J'ai pas vraiment trouver de gain !!!

Je dirais même que pour les boucle For Next il y a un leger
avantage (grande boucle).

Donc les amis continuez a utiliser For Next ...

Afyn
Navedac

PS si tu veux je t'envois le petit prog de test par mail.


Commentaire de Afyn le 24/01/2004 11:34:37

Rectification ...

Il y a un leger gain pour DO While

Mais bon c'est pas flagrant

A+

Afyn

Commentaire de Proger le 24/01/2004 14:33:31

Heu... ouais... c'est pas flagrant... l'algo dans l'exemple n'est pas extra...
En revanche, c'est plus sensible (parfois bcp+) dans ceci :

avant :
Dim i as long, j as long
for i = 1 to 1000
   'code...
  for j = 1 to 1000
    'code
  next j
next i

après :
dim i as long, j as long
i=1
do while i &lt;= 1000
  'code...
  j=1
  do while j &lt;= 1000
    'code
  j=j+1:loop
i=i+1:loop

En gros c'est avantageux dans les boucles imbriqués, surtout si les "incrementals" (i, j) sont utilisés pour la déclaration des boucles interne (do while j &lt; i ...).
Maintenant tu me diras "on en fait pas tout les jours des boucles imbriqués" ... arf :)

ps : "Navedac" ??

Commentaire de Afyn le 24/01/2004 18:20:45

Pour afficher des User Control (et les rafraichir) y a t-il une
méthode d'optimisation ?

Afyn

(National Association of Vilgenis, Erudits, Dundees And Carrierist )

ou

(Nez Au Vent Et Doigt Au C....


... Au Ciel surement !)

Commentaire de Drakkhen le 02/02/2004 08:30:38

Conseils utiles et assez complets, merci :o)
Mais y'a 2-3 trucs qui me paraissent un peu floues...


'Avant
If b &gt;= 0 And b &lt; 255 Then
    a = 32767
End If

'Après (à utiliser avec précaution)
If (b And 255) = b Then
    a = 32767
End If

Dans la première vérification, tu admets une valeur allant de 0 à 254, mais dans la deuxième, tu admets en plus la valeur 255.


Sub DecomposeRGB(Couleur As Long)
    'Avant (maths)
    cb = Int(Couleur / 65536)
    cg = Int((Couleur - cb * 65536) / 256)
    cr = Couleur - cg * 256 - cb * 65536

    'Après (bitmask)
    cb = Couleur And 255&
    cg = (Couleur And &HFF00&) / 256&
    cr = (Couleur And &HFF0000) / &H10000
End Sub

Là, il me semble que tu as inversé les variables "rouge" et "bleu" dans le 2me exemple. :o)


'Après (selon besoins de préçision)
Declare Sub Sleep Lib "kernel32" (ByVal DureeMS As Long)
Sub Wait2(Duree As Single)
Dim t1 As Single
    t1 = Timer + Duree
    Do While Timer &lt; t1
        DoEvents    '&lt;= evite de bloquer le système
        Sleep 1&    '&lt;= libère le CPU pendant 1 milliseconde (évite de chauffer)
    Loop
End Sub

Le Sleep est une bonne idée pour libérer un peu le CPU, mais le problème (comme les contrôles Timer, l'API GetTickCount, et du style) sont de l'ordre des ~50/~15 ms selon le système d'exploitation (9X/NT). Et ça enlève énormément de précision selon la nature du programme (Animation, DirectX, ...).


Une question concernant les chaînes de caractères, les instructions Left$, Mid$, etc... sont-elles différentes des Left, Mid, etc... ?

En tout cas, c'est cool de voir des sources utiles. ;o)

PS : je jurerais que t'étais sur C64 ou Atari vu les I dans les boucles.. :o)

Commentaire de Afyn le 02/02/2004 08:53:15

-&gt; un peu jeune pour Prog sur ATARI !!!

    /|

Vive ATARI

Afyn

Commentaire de mehdibou le 02/02/2004 13:17:16

En réponse à Drakkhen, oui, Mid$, Left$, Chr$ et autres sont différentes de Mid, Left, Chr ... car elles retournent une chaine de caractères (d'où le $) au lieu d'un Variant, et après certains tests on remarque rapidement qu'avec le $ c'est plus rapide car la conversion Variant-&gt;String est supprimée.
Dans tous les cas, un Variant est toujours plus lent qu'un autre type de base.

Commentaire de Drakkhen le 02/02/2004 21:17:59

Ah okay... Je pensais que les expressions renvoyaient toutes une valeur String, merci de l'info. Ce qui veut dire que je vais me retaper vite fait une appli, bref...

Afyn : sauf si on commence tôt, avec le genre d'âge où on est content de découvrir qu'on peut se servir d'une variable :oP

Commentaire de Afyn le 02/02/2004 23:12:09

-&gt; Drakken

Tu as raison, l'important c'est de participer ()

Dans le MSDN, il y a pas mal d'articles sur les optmisations, je pense que ca vaut le coup de les lire. Ca reprend pas mal de chose écrites ici même ...

A+

Afyn

Commentaire de FeelCode le 06/05/2004 19:02:32

Hello

Bon l'optimisation du code je connai pas du tout :P
donc j'ai apris quelque truc sympa ici mai je ne mai pas de note puisque j'y connait rien :
a par cela j'avais fait des test et une boucle

for I= 1 to 100000
next I

Est plus rapide qu'un boucle do ou while:)

En ce moment j'essaye d'aprendre a utiliser des ocx et comme sa rend plus lent le code j'aurai voulu savoir qu'elle pourrait être l'avantage des ocx, car je compte mettre aussi un petit tuto sure les ocx :)

Nix ajoute une section optimisation du code et des interface et temp qu'a faire pour directx :D
Souriez vous ête lu :D

Commentaire de JoePatent le 07/05/2004 21:40:59

si tu Fais un Do...While, VB teste la condition a chaque itération

Avec une boucle For aussi.  Sauf que tu n'as pas a gerer le compteur qui permet de mettre la condition valide pour la sortie de boucle.

Les performances sont équivalente pour les deux type de boucle

Commentaire de krissssss le 06/03/2005 11:59:53

Une petite optimisation pour remplire une picture box avec Pset():

<AVANT>
picture1.Cls

For ix = 0 To 1000
For iy = 0 To 1000
picture1.PSet (ix, iy), QBColor(1)
Next iy, ix

<APRES>

picture1.Cls
For ix = 0 To 1000000
   picture1.PSet (Int(ix / 1000), ix Mod 1000), QBColor(4)
Next ix

<OBSERVATIONS>

Dans la 2ème méthode on gagne 1 seconde d'éxécution en myenne.
Bisarement, on effectue des calculs et une conversion dans cette 2ème façon.
De plus, on a une variable en moins !!!
A-t-on un gain en mémoire ?

Merci aux nombres premiers ;-)

Commentaire de Renfield le 07/03/2005 09:26:40 administrateur CS

étrange, en effet... tu gagnerais davantage, je pense, en ne recalculant pas tout le temps QBColor(4)...(bien que ce ne soit pas l'objet de ta demonstration)

Commentaire de crenaud76 le 15/03/2005 18:14:43

Je viens de découvrir ce tuto, et je reviens sur l'histoire d'utiliser les With et End With ou pas !
Je n'ai jamais désassembler une source VB de ma vie, mais je peux dire que tous les tests que j'ai pu faire sur le sujet (optimisation de la vitesse du code) m'ont amener à penser que With ... End With fait toujours gagner du temps ! Et encore plus si on le sort des boucles, bien sûr !! Et les imbrications de With ... End With sont aussi avantageuses.
Pour finir, je reviendrais aussi sur le cas de ceci ...

'Avant
If b = 27 Then
    a = True
Else
    a = False
End If

'Après
Dim a As Boolean
a = (b = 27)

JoePatent trouve la solution 'Après' pas du tout lisible !! Moi cela me parle bien ! Peut-être est-ce parce que j'ai fait du C avant le VB et que a = (b==27) est totalement lisible en C et que le fait que l'opérateur d'affectation et celui de comparaison de l'égalité sont identique en VB, contrairement à ceux du C !! Ce qui en soit est déjà une entrave à la bonne lisibilité du code VB, mais on va pas réinventé VB maintenant !! Alors allez jusqu'à dire qu'un code est plus lisible s'il comporte plus de ligne, j'en suis pas sur du tout. Moi, je préfère 4 lignes bien claire que 12 trop longues !!! Cela reste une affaire de goût. L'important c'est que si tu maintiens ton propre code, il te faut adopter une ligne de conduite (pour pondre des lignes de code, justement) qui te convienne et si tu maintiens du code de groupe ou qu'un groupe maintient ton code, il faut impérativement que le groupe se mette d'accord avant de pondre la moindre ligne de code.
sinon je met un 10/10 au tuto, même si comme certain, je connaissait la plupart des astuces (certaines on toutefois retenu toute mon attention !!!)

Commentaire de JoePatent le 15/03/2005 19:23:57

crenaud76 ->"Alors allez jusqu'à dire qu'un code est plus lisible s'il comporte plus de ligne, j'en suis pas sur du tout. Moi, je préfère 4 lignes bien claire que 12 trop longues !!! "

Ca ne repond pas a la premisse de depart.  OPTIMISATION signifie avoir un gain de performance.

Tes 4 lignes sont-elles plus performantes que les 12 lignes ?  Si il n'y a pas de difference, pourquoi mettre ca dans un TUTORIEL d'optimisation.

Si tu veux me citer, fais le comme du monde !  voici ce que j'ai dit : "Tu ne gagne rien a procéder de la sorte, tu as juste moins de ligne mais aussi moins de clareté."

Où vois-tu "pas lisible du tout" dans cet extrait hors contexte ?

N'importe quoi...

Commentaire de Afyn le 15/03/2005 20:21:36

Restez zen ...
C'est de l'optimisation ... pour une bonne vie et une
bonne collectivité.

Allez bonne prog à tous

Afyn - Navedac

Commentaire de crenaud76 le 16/03/2005 11:19:25

JoePatent < Je suis tout a fait d'accord avec toi ! Il est posible que 12 lignes de code soient pus rapide que 4 ! Mais à vitesse égal, je préfère les 4 lignes.
Excuses-moi encore d'avoir écorner tes propos !
sans rancune ?

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,905 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales