SetBitmapBits versus BitBlt

cs_cheyenne Messages postés 693 Date d'inscription samedi 18 mai 2002 Statut Membre Dernière intervention 17 avril 2017 - 26 janv. 2013 à 22:28
cs_cheyenne Messages postés 693 Date d'inscription samedi 18 mai 2002 Statut Membre Dernière intervention 17 avril 2017 - 28 janv. 2013 à 13:41
Bonjour,

Je déplace des objets sur une Picture. Avant chaque déplacement une grille contenue dans une autre Picture est copiée sur la feuille des objets avec un BitBlt.
Je voudrais savoir si il n'est pas plus intéressant de copier la grille avec GetBitmapBits puis supprimer la Picture de la grille et la coller avec SetBitmapBits plutôt que d'utiliser un BitBlt et conserver la Picture de la grille.
Est-ce que le tableau des bits prend en mémoire plus de place que la Picture en AutoRedraw qui contient la grille ?.
Je pense qu'en terme de rapidité le SetBitmapBits est beaucoup plus rapide que le BitBlt, mais en place mémoire qu'en est-il ?

Merci,

Cheyenne

5 réponses

rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
27 janv. 2013 à 18:13
Dommage j'étais aussi intéressé par l'utilisation de SetBitmapBits, mais faute de temps, est comme maintenant cela marche bien avec bitblt + mes procédures en ASM je ne veut pas perdre plus de temps !
mais si c'est vraiment plus rapide, j'espère que tu commentera un peu de ton expérience !
0
cs_cheyenne Messages postés 693 Date d'inscription samedi 18 mai 2002 Statut Membre Dernière intervention 17 avril 2017 2
28 janv. 2013 à 00:03
Bonjour rebixav,

Ci-dessous la manière dont je teste la vitesse d'exécution des codes.
Voici comment je procède, je fais 2 tests.
Chaque test est fait 5 fois (nTEST), dans chaque test le code est exécuté 1000 fois.
J'enregistre les temps pour chaque test et fait un tableau comparatif.
Finalement BitBlt est en moyenne 2.88 fois plus rapide que SetBitMapsBits pour une image de 800x800. J'aurais pensé l'inverse. !
Private Sub testSetBitMapBits()
   Dim bit(3, 799, 799) As Byte
   Const nOCTETS As Long = 800& * 800& * 4
   Call GetBitmapBits(picBIT(0).hdc, nOCTETS, bit(0, 0, 0))
   
   lblINFO(1).Caption = "SetBitMapBits"
   For i = 1 To nTESTS
      Call QueryPerformanceCounter(ticDEB)
      For j = 1 To 1000
         Call SetBitmapBits(picBIT(0).hdc, nOCTETS, bit(0, 0, 0))
      Next j
      Call QueryPerformanceCounter(ticFIN)
      temps(1, i) = (ticFIN - ticDEB) / ticFRQ
   Next i
   
   lblINFO(2).Caption = "BitBlt"
   For i = 1 To nTESTS
      Call QueryPerformanceCounter(ticDEB)
      For j = i To 1000
         Call BitBlt(picBIT(0).hdc, 0, 0, 800, 800, picBIT(1), 0, 0, vbSrcCopy)
      Next j
      Call QueryPerformanceCounter(ticFIN)
      temps(2, i) = (ticFIN - ticDEB) / ticFRQ
   Next
End Sub

J'ai fait plein de test sur différents code afin d'optimiser. Par exemple a VbNullString est 22 fois plus rapide que a "".

Cheyenne
0
cs_cheyenne Messages postés 693 Date d'inscription samedi 18 mai 2002 Statut Membre Dernière intervention 17 avril 2017 2
28 janv. 2013 à 00:09
Re,

Quand je te disais que le code est exécuté 1000 fois, ce n'est pas toujours le cas. C'est pour cela que je n'ai pas mis de Constant pour 1000.
Sinon dans l'ensemble je boucle nFOIS (1 million).

Voilà, cela peut te servir pour tester la rapidité de tes codes !

Cheyenne
0
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
28 janv. 2013 à 09:36
bon ben c'est une bonne nouvelle, car cela m'aurrais embetter de devoir taper encore du code déjà fait ! merci pour l'info : a = VbNullString
...
moi aussi j’adore les statistique et la vitesse, j'en ais fait des tonnes de test, en basic et en ASM !
mais je pense que tu sait aussi que l'ordre de vitesse des variable sous vb6 en tant que puissance (du plus rapide au plus lent est :
- booleans, integer, long, single, curency, et enfin byte !
et que d'un cpu intel à un cpu amd, il peu avoir des grosse différence :
exemple sur intel des fois le single est plus rapide que le integer

et aussi que le code est plus rapide dans un module ou une class que dans une form ou un bouton :
- for next => dans form = 380 million / s
- for next => dans module = 760 million / s
- que travailler dans un tableau long(x)=348 million / s
- que travailler dans un tableau long(x,x)=164 million / s
- que travailler dans un tableau long(x,x,x,x,x)=75 million / s
(plus il y de tableau plus le compilateur pour ce positionner dans la mémoire doit faire des
calcul de multiplication !

et un dernier truc que tu doit savoir aussi :
- call une sub = 400 million / s
- alors qu'un simple goto = 900 million / s
- donc je me suis dit qu'un gosub irais à 450 million / s au moins, et bien non = 11 million / s


bref...
moi j'utilise :
CHRONO
for i&=1 to 1000...
>> ce que je veut tester !
next i&
CHRONO_END

Public Sub CHRONO()
chrono_timer_pour_test = Timer
End Sub

Public Sub CHRONO_END(Optional ByVal Commentaire As String = "")
t2! = Timer - chrono_timer_pour_test
If t2! < 1 Then a$ "0" + STR2$(t2!) Else a$ STR2$(t2!)
a$ = Commentaire + a$
MsgBox a$
End Sub

...

en faite j'ai pas bien compris ta méthode ou il me manque des bouts :
Call QueryPerformanceCounter(ticFIN) ???
ticFRQ ???

...
ha si un dernier truc, j'ai appris que même programmer en code machine(assembleur), n'est pas le plus rapide, soite je gagne entre 2 et 10 fois le basic, mais c'est l'optimisation du code qui est le plus rapide, et une des méthode que j'utilise de plus en plus fréquemment est bien sure les "Prédilection"
- exemple : a$=chr$(150) = 3 million / s alors que a$=chr2$(150) = 10 million / s
En faite c'est simple je profite de lire en mémoire des résultats déjà calculé pour un peu de tout !
"chr2$" n'est pas une function mais un tableau, ayant déjà les caractère préparé
plus je prévoit, plus j'évite des calculs et plus je suis rapide, certain me permettent de gagner jusqu'à 1000x , et quelque fois ce n'est qu'une petit ligne de rien du tout à rajouter avec une petite variable de plus !
je préfère par exemple utiliser à toutes les étapes le REDIM PRESERVE, que le REDIM !
- redim = 0,085 million / s
- redim preserve = 8,42 million / s

...
allez à+
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_cheyenne Messages postés 693 Date d'inscription samedi 18 mai 2002 Statut Membre Dernière intervention 17 avril 2017 2
28 janv. 2013 à 13:41
Re,

Pour les optimisations que tu indiques, je connaissais, mais merci quand même !.

A noter que les variables typées sont en moyenne 2.6 plus rapides que celles qui ne le sont pas.

Call QueryPerformanceCounter(ticFIN) ???
ticFRQ ???

C'est une fonction de l'API qui est beaucoup plus précise que le Timer.

ticFREQ est la vitesse horloge du processeur qui est déterminée avec QueryPerformanceCounter.

Pour en savoir plus je t'invite à ce sujet à consulter ce lien :
http://allapi.mentalis.org/apilist/QueryPerformanceCounter.shtml
C'est vraiment passionnant de chercher à optimiser le code, mais bon il ne faut pas non plus chipoter pour quelques 1000ème de seconde si on exécute le code que peu de fois.

a+ Cheyenne
0
Rejoignez-nous