Newsgroup: it.comp.lang.visual-basic
Titolo: Quale codice è più veloce. Benchmark su VB

Mi sono sempre chiesto ogni volta che scrivevo codice su VB quale codice
fosse più veloce, se è meglio usare for/next o do/loop, se è più veloce
assegnare direttamente un valore o una variabile, se è più veloce if/then o
select/case e così via. Magari if/then è più veloce, ma di quanto ?
Così ho scritto un programma per fare dei benchmarks e ho scoperto alcune
cosette interessanti. Se vi interessa sono riassunte qui sotto.
Se qualcuno scrivesse dei benchmarks e arrivasse a risultati in contrasto
con
i miei mi farebbe piacere se me li comunicasse.
Ogni benchmark consiste in un loop for/next di 10 milioni di volte,
all'interno del quale ho inserito un cronometro e di volta in volta il
codice da testare. Ho eseguito i test parecchie volte, ma i risultati sono
sempre stati confermati.
La prima cosa che ho messo alla prova sono i tipi di variabili, nel test ho
eseguito 10 milioni di assegnazioni e 10 milioni di operazioni.
Il più veloce è il Boolean: 8.1 secondi, seguono integer (10.3) e long
(11.0), dalla rapidità molto simile.
Single (13.9) e Double (14.1) hanno la stessa velocità (chissà perchè mi
immaginavo che double fosse stato molto più lento, quasi il doppio e
invece...).
Il Currency è ancora più lento del Double. Ben 15.8 secondi.
Una grande sorpresa è stato il Byte, pensavo fosse il più veloce di tutti,
qualcosa come 2-3 secondi, e invece ben 17.8 secondi ! Quindi penso che per
i numeri piccoli userò d'ora in poi l'integer che è doppiamente veloce e il
long per tutti gli interi normali, tanto la differenza con l'integer è molto
piccola.
Il Variant, credevo fosse molto lento, come appreso dai manuali, e invece
18.0 secondi, come il Byte...
Segue lo String con una rapidità di 40-60 secondi a seconda della lunghezza.
La vera sorpresa è stata il Date, di una lentezza paurosa ! Fare operazioni
con le variabili di data/ora è circa 2000 volte più lento rispetto al long !
Per i dati personalizzati la velocità dipende dal contenuto, ma hanno la
stessa velocità dei tipi di cui sono composti. Ad esempio usare un A.B dove
B è un integer richiede 10.4 secondi, cioè come se si usasse un integer.
Poi ho considerato gli operatori di decisione if/then e select/case.
Ho scoperto che Select/Case è più del triplo più lenta di if/then, 23.2
secondi contro 7.0 (if/then in riga singola). If/then/else/end if richiede
invece 13.5 secondi.
Ho considerato inoltre i cicli for/next e do/loop. Un ciclo for/next è molto
più veloce (8.3 secondi) di do/loop (14.5 secondi).
Inoltre mi sono chiesto se scrivere A=2000 era lo stesso che scrivere A=B,
dove B era stato impostato prima a 2000. L'operazione è identica (6.0
secondi). Avevo letto da qualche parte che era molto più veloce A=B. Boh.
Usare una matrice (anche monodimensionale) richiede il 50% del tempo in più
rispetto a una variabile semplice. Mentre il dimensionamento di una matrice
mono-, bi-, tridimensionale, statica o dinamica richiede lo stesso identico
tempo.
I commenti non rallentano minimamente l'esecuzione del programma. Ho
inserito 1 milione di commenti e ho avuto un rallentamento di 0.3 secondi.
Infine ho considerato quanto influisce sulla velocità scrivere il codice in
una procedura o usufruire (chiamare) una procedura o funzione ulteriore.
La chiamata di una Sub o Function esterna equivale a fare un'assegnazione e
un operazione con una variabile Variant (18 secondi).
Sono graditi i commenti
Tanto non rallentano il codice ! ;-)

 Tanto non rallentano il codice ! ;-)
Grazie delle informazioni.
Altre informazioni sulla velocita di esecuzione si possono trovare qui:
http://www.freeweb.org/internet/FLAVIONET/homepage.htm
Non ho avuto ancora il tempo di confrontarle ma sarei curiosio di vedere se
ci sono differenze sostanziali, infondo incide molto anche il metodo usato
per cronometrare i tempi.
Ciao
Daniele
---------------------------------------------------------------------------
Le risposte alle tue domande le trovi sul Sito Comune di questo NewsGroup:
 
http://www.murialdo.it/it_lang_vb
---------------------------------------------------------------------------

con i miei mi farebbe piacere se me li comunicasse.
L'unico modo di dare un minimo di scientificita' ad un benchmark di
questo tipo e' che il codice, almeno delle parti in cui avviene
effettivamente la misurazione, sia pubblico. Altra cosa su cui
accordarsi e' il modo di fare il test (media di 3 prove o piu'?).
Comunque complimenti per il lavoro!
Ciao
Gian Michele Bertoni
homepage: 
http://space.tin.it/computer/gbertoni

 --------------------------------------------------------------------------


 Comunque complimenti per il lavoro!
Grazie


 all'interno del codice di misurazione.
Non intendevo questo.... Dicevo solo che probabilmente ci sarà qualche
differenza fra i risultati di Flavio e i tuoi visto che, quasi sicuramente,
avete usato metodi differenti per il solito fine...
Ciao
Daniele
--------------------------------------------------------------------------


accordarsi e' il modo di fare il test (media di 3 prove o piu'?).
Non dimentichi la cpu? e la ram? Anche quelle cose sono molto
importanti!!!
ByeZ!
Alkondor

importanti!!!
Non necessariamente, se consideri il rapporto che c'e' fra le prove e
non il loro valore assoluto.
Ad esempio, scegli un prova (p.e. assegnamento di un intero) e dividi
ogni prova per il valore di questa.
I diagrammi con combinazioni di CPU e/o di RAM diversi dovrebbe essere
confrontabili. Molta piu' influenza dovrebbe averla il sistema
operativo (Win9x o NT), ma e' una cosa che consideravo sottintesa (ho
gia' pubblicato su questo newsgroup dei benchmark con serie di valori
diverse per i due SO).


 avete usato metodi differenti per il solito fine...
No. I tempi sono diversi perchè i test riguardano cose diverse.
Lui con le variabili ha eseguito solo calcoli (+-*/) io invece oltre ai
calcoli ho inserito anche l'istruzione più usata, cioè quella di
assegnazione (=). E' lì che si vede la differenza.


 Alkondor


Non vorrei gettare benzina sul fuoco... capisco l'utilità dei valori
relativi (molto comodi per avere un'idea delle prestazioni del
programma), però le prestazioni sono pesantemente influenzate
dal tipo di CPU. Ad esempio se facessi il test dei double su
un 386 (senza FPU) avrei un'enorme differenza di prestazioni rispetto
ai logn e avrei prestazioni ancora migliori con gli integer.
Le CPU attuale (Pentium e i suoi derivati) hanno un'ottima
FPU integrata, che annulla (quasi) le differenze tra Long e Double
(o Single). Comunque con i K6 troveri risultati migliori sui Long e
Integer, rispetto ai Double, mentre con i Pentium II/III avrei risultati
migliori (rispetto ai K6) nei calcolo con i double.
In sostanza, è importante il tipo di CPU.

In sostanza, è importante il tipo di CPU.
Le tue considerazioni le trovo giuste e sicuramente dovrebbero essere
inserite come avvertenze nel programma di test. Tuttavia, se la
necessita' di un double e' giustificata dalle esigenze di un algoritmo
c'e' anche poco da scegliere...



....


Non sono completamente d'accordo, infatti è quasi (se non sempre)
possibile trasformare un problema che usa double in un problema
che usa integer (il vecchio fractint è un esempio spettacolare).
Così come puoi trasformare moltiplicazioni
e divisioni in somme e sottrazioni (usando le proprietà dei logartmi).
Ovviamente erano tecniche che avevano senso ai tempi degli 8088
(nostalgia..) e oggi (con cpu che calcolano funzioni trascendenti
in un solo ciclo clock o peggio usando le tecniche SIMD) fanno sorridere,
e anzi, sono controproducenti (ad esempio puoi simulare la
moltiplicazione con alcuni ROL e alcuni ADD, però se l'opcode
MUL viene eseguito in un solo ciclo, peggiori
la situazione).
Saluti, Massimo

 Single (13.9) e Double (14.1) 
Ciao, e complimenti per la perseveranza dimostrata: io mi ero scocciato
dopo aver fatto poche prove sugli integer...Proprio a questo riguardo,
avevo trovato dei risultati leggermente diversi dai tuoi: in particolare
avevo scoperto (facendo dei cicli in cui aumentavo un contatore) che la
procedura con il contatore long era leggermente piu' veloce (ci metteva
il 99% del tempo) di una in cui il contatore era integer (ho un P100 72
MB RAM  W95 OSR2 VB5 SP3). Ad essere sincero, mi ero accontentato di
sapere che uno era un filo piu' veloce dell'altro, e bon. Ora sarebbe
interessante scoprire le ragioni della differenza di comportamento tra
il tuo codice ed il mio... Se ti interessa posso mandartelo (saranno 10
righe in croce, ma qui non le ho, devo passare da casa a prenderle...)
Ciao
Brando
-- 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Sito comune di it.lang.vb  :  
http://www.murialdo.it/it_lang_vb
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

che usa integer (il vecchio fractint è un esempio spettacolare).
Dovresti rileggerti (io l'ho fatto) il doc del fractint: le
limitazioni (di numero di decimali e di massimo numero
rappresentabile) possono essere tali da dover passare (come appunto fa
fractint in certe situazioni) dalla matematica intera a quella in
virgola mobile. Interessante, a questo proposito, il thread sulle
derivate.
Comunque non vorrei farla piu' lunga di quello che e': ho ben presente
la "soluzione fractint" ed infatti ho scritto "giustificata dalla
esigenze di un algoritmo".


 darti il tempo che ha macinato il tuo (e solamente il tuo) Thread.
Non ho usato Timer.
Ho fatto con un cronometro vero, molte volte e poi ho fatto la media.
Lo scarto tra i risultati era dell'ordine di 1-2 decimi di secondo.
Ho poi confrontato i risultati con una routine che calcolava la differenza
dell'orario del computer e i risultati corrispondevano.
Ciao



Hai perfettamente ragione.
Era un K6, per cui con i Pentium I/II/III la differenza č ancora piů
sottile.
Quello che č interessante, a mio parere, č la lentezza dei Byte rispetto
agli altri e dei Date (2000 volte piů lenti).
Per quanto riguarda gli altri tipi di test non credo che la CPU (o la Ram)
possano cambiare i risultati dei test.
Ciao
PS: in ogni caso non penso che qualcuno usi il Vb5 con il 386.



 righe in croce, ma qui non le ho, devo passare da casa a prenderle...)
Nel test ho inserito un'assegnazione A%=100 e un'operazione A%=A%*100
Tu cos'hai inserito ?
In ogni caso il succo è che la differenza è così lieve che ho deciso di
usare sempre il long per gli interi normali e l'integer per i numeri piccoli
dove prima usavo Byte, che invece è molto più lento. Non userò mai più Byte.
Ciao



In che senso un cronometro "vero"???
No, non dirmelo, ho paura di saperlo!
--
Roal Zanazzi
z...@iol.it

 No, non dirmelo, ho paura di saperlo!
Perchè ? Pensi che non sia abbastanza preciso ? Di quanto pensi sia l'errore
con tempi così lunghi ? A parte che ho fatto parecchi test e poi ho fatto la
media, ma se anche mi fossi sbagliato di 3-4 decimi a ogni test, i risultati
su tempi di 15-20 secondi sarebbero lo stesso abbastanza precisi.
Se poi ti servono i centesimi di secondo allora devi collegare un orologio
atomico al computer, ma dubito dell'utilità di tanta precisione...
Bye