Collection Vs Array

di il
5 risposte

Collection Vs Array

Pongo un tema tecnico.
Uso spesso le Collection al posto di Array, questi 2 tipi di oggetto, differenti, hanno performances molto diverse a seconda di come vengono impiegate.
Chiaramente la differenza non si nota in azioni singole, ma su azioni massive.

Le differenze più corpose che rilevo, sono nelle azioni di Aggiunta, e di Ricerca.
Ora sia sugli Array che sulle collection si apre un capitolo a parte, entrambi offrono prestazioni differenti in fase di Aggiunta a seconda di:
1) Array Statico o Dinamico
2) Collection con o senza l'uso della Key

In sostanza ho che:
Array Dinamico (ridimensionabile a Runtime con Redim Preserve)
AGGIUNTA Lento
RICERCA, essendo già dimensionato basta ciclare, è relativamente veloce

Array Statico

AGGIUNTA Molto veloce, direi l'oggetto più performante, peccato non sia flessibile e sapere Ubound non sempre è noto.
RICERCA come sopra

Collection Senza uso di KEY

AGGIUNTA Un poco Lenta, ma a metà tra Array Statico e Dinamico
RICERCA Lentissima da non usare in ciclo indicizzato, se si usa For...each invece è confrontabile con Array

Collection con uso di KEY

AGGIUNTA Lenta, circa x10 rispetto all'array dinamico e x20 rispetto allo statico
RICERCA Molto Veloce, si sfrutta l'indicizzazione della KEY String, oggetto più veloce

Un Test su 100000 Iterazioni, ovviamente ho cercato l'ultimo Item inserito:

ADDITEMS
ReDimArray 100000 items in 0,04296875 seconds.
NO ReDimArray 100000 items in 0,0234375 seconds.
Collect NOKey 100000 items in 0,03515625 seconds.
CollectionKey 100000 items in 0,4453125 seconds.

SEARCH
Find Array  : I100000 in 0,03515625 seconds.
Find Coll NoKey I100000 in 35,59375 seconds (usando ciclo indicizzato su Item)
Find Coll NoKey I100000 in 0,0332569 seconds (usando For Each)
Find Coll. Key I100000 in 0 seconds.
Se passiamo ad un Test su 1000000 di dati:

ADDITEMS
ReDimArray 1000000 items in 0,8945313 seconds.
NO ReDimArray 1000000 items in 0,203125 seconds.
Collect NOKey 1000000 items in 0,3710938 seconds.
CollectionKey 1000000 items in 5,105469 seconds.

SEARCH
Find Array  : I1000000 in 0,3320313 seconds.
Find Coll. Key I1000000 in 0 seconds.
Detto questo ognuno in base a quello che deve fare si orienta, purtroppo non sempre si conosce a priori quanti elementi devono essere inseriti, quindi l'uso di Array Statico risulta meno indicato, e quello dinamico in caso di Inserimento è lento.

Tutto questo pippone, perchè per quello che serve a me devo avere la massima velocità nella ricerca, quindi devo usare Collection con l'uso della KEY, e volevo migliorare sensibilmente la velocità di inserimento che come si vede dai test è circa 10 volte superiore a quella di un'array.

Ricordo che nel sito comune di VB6, per i vecchi come me lo ricordano sicuramente, AntonioG ne sono certo(intendo che lo ricordi non che sei vecchio ), era stato pubblicato un demo di una ClasseCollection che sfruttava un Mix dei 2 Oggetti ed otteneva ottimi risultati in termini di performance.
Purtroppo il sito è saltato da parecchio ed io non trovo più nulla, quindi speravo in qualcuno che ricordasse la logica seguita, o se avesse un'idea da suggerire, per sviluppare questa cosa e provare a ricostruire qualche cosa di funzionale.

5 Risposte

  • Re: Collection Vs Array

    Ma quello che si trova su access group non è il sito comune completo?
    Comunque, di primo acchitto, mi è venuta la soluzione della serva.
    All apertura del database calcoli la grandezza delle tabelle ed usi sistemi diversi in base alle esigenze.
  • Re: Collection Vs Array

    Ho parlato del sito comune di VB6 quando c'era, il demo era di ZANNA, il sito.comune di Access è vecchio come me e metà del materiale era mio

    Temo non sia l'interpretazione corretta del problema quella esposta.
    L'esigenza è generalizzata ma non generica...
    Il problema non è tabelle database ma VBA e performance del VBA.

    Immagina di avere un sistema gerarchico di classi a livelli infiniti... per semplificare un TreeView con i Nodi.
    La cosa si gestisce con Collection di classi nella casse padre, per gestire la gerarchia Childs.
    Ogni classe può istanziare infinite classi childs, logica OOP, almeno per quanto si può fare in VBA.

    La ricerca del singolo Item deve avvenire in modo veloce quindi si sfruttano 2 Colection, una gerarchica nella classe ed una nella Root di tipo
    Seriale senza gerarchia con Key questo evita di dover cercare in ricorsione l'item... ma l'aggiunta o la popolazione del sistema quando si riempie massivamente l'albero si sente...
    La compilazione della collection seriale che viene rigenerata ad ogni ADD... impiega tempo relativamente lungo e volevo migliorarla in qualche modo, anche perché il tutto è legato poi a della grafica API con GDI+.

    So che l'argomento non è proprio di semplice comprensione essendo rivolto allo sviluppo OOP.... ma parliamo di questo
  • Re: Collection Vs Array

    Fuori dalla mia portata.
    Non essendo un programmatore professionista, ma un appassionato al limite del lamer (non cracco sistemi sia ben chiaro, come detto ho la mia collezione di codice che riuso all occorrenza), la mia conoscenza non arriva a questi livelli. Dovrei rimettermi a studiare seriamente, su un argomento che poi all atto pratico non sfrutterei.
    Mi ricorda molto il problema che si aceva da giovani quamdo bisognava sdegliere la campana della vespa modificata. Corona con tanti denti da poter sfruttare le marce alte e quindi più velocità, oppure corona con pochi denti che riuscivi ad impennare in quarta, ma che poi non ti faceva superare gli 80 km orari?
    Rimanendo suull astratto, Per quanto mi riguarda pero, come detto, se fosse possibile usarli sullo stesso oggetto, creerei due sistemi e li attiverei in base all esigenza, oppure sceglierei quello che mi garantisce prestazioni elevate con maggior carico di lavoro. Visto che la vera differenza si percepisce solo con grossi carichi.
    Comunque per lavoro, mi sono trovato davanti a programmi gestionali (costosissimi)che per assegnare un migliaio di prodotti da spedire ai vari clienti, in base agli ordini, impiegavano nottate intere, e se la procedura veniva attivata di giorno, tutto il programma si rallentava impedendo di lavorare.
    Quindi mi rendo conto che il problema è serio ed impegnativo.
  • Re: Collection Vs Array

    Alex hai esaminato l'aspetto della diversità nei tempi (al crescere del numero di elementi negli arrays e collections) legati al sort impiegato?
    Nel primo link si evidenzia un grafico dei tempi (legato al sort ed numero elementi) ove si evidenzia il preferenziale algoritmo di MergeSort al posto del BubbleSort.
    https://stackoverflow.com/questions/3587662/how-do-i-sort-a-collection
    https://www.erlandsendata.no/?t=vbatips&c=recent&p=408

    Valuta l'oppotunià (con i vincoli del caso) di impiegare gli oggetti Dictionaries al posto delle Collections, quando questi assicurano tempi più veloci:
    https://newtonexcelbach.com/2013/08/29/arrays-vs-collections-vs-dictionary-objects-and-dictionary-help/
    https://stackoverflow.com/questions/32479842/comparison-of-dictionary-collections-and-arrays
    https://stackoverflow.com/questions/45965559/vba-sorting-a-collection-by-value
  • Re: Collection Vs Array

    Ciao Willy, ben risentito.

    Gli articoli che hai riportato li avevo già analizzati... qualcuno effettivamente da spunti interessanti, vedo ultimo paragrafo sotto sui SafeArray.

    Non ho necessità di Sort, e questo in parte mi scarica da una quota parte della problematica.

    Sui Dictionary, che ho provato, le performance sono relativamente simili per il mio utilizzo, diventano molto interessanti in quanto hanno metodi nativi utili già esposti, ma per le prove fatte per il mio scopo non sono risolutivi almeno come performance, oltretutto da istanziare LateBinding come oggetti esterni.

    Per farti magari capire meglio, per la mia esigenza, le collection vanno benissimo salvo in fase di ADD massivo che sono lentisseime.
    Perchè questo mi da fastidio...?

    Perchè gestendo un sistema gerarchico di Classi in cui ogni Oggetto può avere Figli, come dicevo l'esempio del TreeView chiarisce, se devo ricavare l'oggetto in un ramo del Tree, senza dover ciclare ricorsivamente tutto l'albero, ho una Collection Parallela in cui serializzo l'albero con tutti gli Items, in questo modo recupero l'istanza della classe e in tempo zero gestisco l'istanza.
    Se io gestisco questa gerarchia, sono costretto a cercare sempre in modo ricorsivo finchè non trolo l'istanza che mi serve
    
    Classe-0
       ----> Classe-0-0
       ----> Classe-0-1
               ----> Classe-0-1-0
               ----> Classe-0-1-1
                       ----> Classe-0-1-1-0         <--- Ipotizza di dover trovare questo...
               ----> Classe-0-1-2
       ----> Classe-0-2
    Classe-1
    ...
    Non puoi sapere dove si trova, o meglio non sai in quale Collection cercare, fa parte della Collection CHILDS di [Classe-0-1-1] ma devi arrivarci..., e lo puoi fare partendo dalla ROOT ed iniziando a scendere di livello, quando arrivi al PARENT allora nella sua Collection usando la Key lo trovi... questo metodo è poco molto poco efficiente.
    Se invece parallelamente alla gestione gerarchica, nella ROOT mi creo una collection seriale:
    
    Classe-0
    Classe-0-0
    Classe-0-1
    Classe-0-1-0
    Classe-0-1-1
    Classe-0-1-1-0          <--- Ipotizza di dover trovare questo...
    Classe-0-1-2
    Classe-0-2
    Classe-1
    ...
    In questo modo, lo trovo per KEY in T=0s, e recuperata l'istanza so chi è il Parent e chi sono i Childs.

    Questo ovviamente richiede che, ad ogni AddItem o RemoveItem dall'albero io vada a rigenerare la collection Serializzata in ROOT.
    E' proprio questa attività che devo velocizzare, in quanto con la Collection con KEY i tempi di ripristino non sono così leggeri.
    Uno potrebbe chiedere... perchè devi rigenerarla tutta...?
    Perchè la collection Seriale viene usata poi per la gestione GRAFICA in quanto anche quì molto veloce da ciclare non dovendo fare ricorsione, quindi se aggiungo un Item in Gerarchia, deve essere inserito nella Collection Seriale nel punto giusto non alla fine...

    Spero di aver chiarito un poco gli aspetti di logica.

    Ora da quanto ho visto l'idea potrebbe essere quella di usare un SafeArray in memoria, che emula una Collection, questo fa uso non tanto degli Oggetti nativi del VBA quando dell'approccio che anno linguaggi più strutturati, quanto dei Pointers degli oggetti in memoria, un metodo che in linea teorica ho compreso ma mai usato... ma soprattutto non so se veramente più performante.
    Ho trovato un paio di esempi su vbAccelerator, faccio qualche test... poi ci studio sopra.

    Grazie
Devi accedere o registrarti per scrivere nel forum
5 risposte