posts - 644, comments - 2003, trackbacks - 137

My Links

News

Raffaele Rialdi website

Su questo sito si trovano i miei articoli, esempi, snippet, tools, etc.

Archives

Post Categories

Image Galleries

Blogs

Links

Collection e container

Sempre riguardo alla famigerata collection v2.0, una delle scelte a cui mi sono trovato davanti è stata quella del container: array o lista dinamica. Le collection del framework come List<T> e derivati usano tutte l'array come container.

La scelta è tutt'altro che ovvia perché naturalmente ciascuna delle due ha i suoi pro e i suoi contro.

Array

  • accesso random e sequenziale super-performante
  • l'aggiunta di elementi richiede la riallocazione dell'array e il loro travaso (tipo redim tanto per capirci) e quindi molto penalizzante
  • la cancellazione elementi richiede di far scalare gli elementi nell'array a meno di non gestirli a macchia di leopardo ma con la necessità prima o poi di ricompattarli (tipo garbage collector)
  • Array.Sort provvede già a performanti algoritmi di sorting che uniti a IComparer e/o IComparable permettono il sorting di qualsiasi cosa

Lista dinamica (single/double linked list)

  • l'accesso random richiede la navigazione di tutta la lista; quello sequenziale è molto performante
  • l'aggiunta di elementi è molto performante
  • la cancellazione è molto performante
  • non ci sono classi pronte per il sorting ma esistono algoritmi molto performanti anche per le double linked list

Mi sono detto: ok, voglio il meglio e quindi implemento il 90% dei metodi con entrambi i contenitori. Poi quando mi serve una caratteristica per la quale uno dei due container è più performante in assoluto, travaso la lista e la uso. E così ho fatto.

Un giorno (ieri) arrivò il tempo dei benchmark di memoria/performance. E arrivarono pure i dolori. Con l'aiuto di Ants e il Performance explorer di VS2005 mi accorgo che il gioco non vale la candela.

Nelle Add la LinkedList richiede ovviamente l'allocazione anche del LinkedListNode e questo fa crescere a dismisura i tempi rispetto anche al travaso dell'array. Si, perché l'array ovviamente non lo si incrementa di solo un elemento ma di un 30-40% rispetto alla sua dimensione attuale.

Alcune operazioni effettivamente sono performanti con le linked list ma come dicevo prima il gioco non vale la candela.

Nelle Remove il lavoro del GC è superiore e questo penalizza nuovamente. Se anche non ci fosse il GC e fossimo con codice unmanaged ci potremmo trovare con memoria super-frammentata, un problema ben peggiore della perdita di performance.

In conclusione, nonostante tutto quello che si dica sulla bellezza delle linked list, in praticalandia è meglio affidarsi al caro vecchio array. Ovviamente parlo del container di una collection, certamente non di usare un array di Order o altro. Il wrapping fatto da una classe di collection è realmente indispensabile per costruire un object model decente.

Se ripenso all'esame di introduzione ai calcolatori digitali in cui il pezzo forte erano proprio le liste dinamiche ...

Print | posted on mercoledì 1 novembre 2006 14:12 |

Feedback

Gravatar

# re: Collection e container

Ciao Giulio,
per poterlo provare la collection doveva necessariamente essere completa. Le operazioni di Add e Remove (tipicamente le più usate) sono tutt'altro che banali in una collection complessa. Ci sono una serie numerosa di cose da fare come aggiornare il filtro corrente sulla base dello stato e del filtro, verificare l'ordinamento, fare l'hook/unhook degli eventi, etc....
Ma di questo ne parlerò tra non molto :-) La prima presentazione della mia collection nuova sarà proprio in wpc fra due settimane.
Ciao!
02/11/2006 11:21 | Raffaele Rialdi
Gravatar

# re: Collection e container

>Se ripenso all'esame di introduzione ai calcolatori digitali in cui il pezzo forte erano proprio le liste dinamiche ...

Una ventina di anni fa la memoria ram era una risorsa preziosa e limitata molto più di quanto lo sia ai giorni nostri.
Dichiarare un array di 1000 elementi (non sapendo a priori quanti elementi avrei utilizzato, magari solo una decina) era, in molti casi, progettualmente sbagliato. Le liste dinamiche risolvevano egregiamente questo problema.

Ciao Pino
02/11/2006 11:50 | Pino Serra
Gravatar

# re: Collection e container

Ma certo, non volevo certo dire che quell'approccio fosse sbagliato. Come scrivevo nel post, la linked list in alcuni casi ha ancora senso. E per esempio sui microcontroller è tuttora una soluzione indispensabile.
Certo però che non conosco testi che mettano in rilievo questa diversa filosofia progettuale, nè mi risulta che nelle università si approcci diversamente all'insegnamento.
02/11/2006 13:09 | Raffaele Rialdi
Gravatar

# re: Collection e container

Ciao Giulio,
la linkedlist a mio parere non è conveniente. Come dicevo nel post basta considerare le allocazioni del nodo che contiene l'elemento per renderlo sfavorevole dal punto di vista del lavoro del GC.
Ad ogni modo anche le prove con il profiler aggiungendo e rimuovendo elementi mi hanno fatto desistere definitivamente.

La sessione c'è stata e a quanto mi hanno detto alcune persone è anche andata molto bene. Si è tenuta la settimana scorsa alla WPC ed era intitolata "Dataset vs Custom Entities".
Ho mostrato la mia collection che è diventata molto grossa.
La classe della collection è 2243 righe splittata su più partial classes.
Il complesso delle classi (quella di prima più un piccolo parser per i filtri, e varie altre implementazioni per le Entities, ma senza alcun codice per accedere ai dati) è di 3387.

Ho fatto la richiesta di un workspace su www.codeplex.com e sto aspettando che mi diano l'ok all'apertura del progetto. Nel frattempo sto creando la documentazione in inglese e traducendo i miei commenti in inglese.
Spero di poterla pubblicare presto.
24/11/2006 15:07 | Raffaele Rialdi
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET