Javascript: Strutture Dati vs DOM

Javascript è un linguaggio di programmazione che per molto tempo è stato considerato come un “toy language” in effetti i suoi principali usi consistevano nella validazione di form lato client e nell’esecuzione di semplici animazioni. A partire dal 2005 grazie ad Ajax ed all’esigenza di costruire applicazioni web più interattive il suo utilizzo è cresciuto notevolmente ed oggi lo stesso viene impiegato per la costruzione di applicazioni desktop, mobili e persino come tecnologia lato server. Uno degli aspetti critici nell’impiego di javascript è l’accesso al DOM che in via teorica doverebbe essere ridotto al minimo, in effetti pensando ad un modello MVC dovrebbe costituire la view, ma spesso e volentieri viene impiegato per collezionare e manipolare dati. L’utilizzo del DOM come contenitore di dati presenta alcuni punti deboli:

  • Prestazioni differenti tra i vari browser
  • Le performance degradano molto velocemente
  • Si costruiscono applicazioni poco modulari
  • Maggiori difficoltà nell’eseguire il testing

Quanto detto è valido in modo particolare quando si implementano applicazioni che gestiscono una grande mole di dati e per renderci meglio conto di ciò possiamo eseguire un semplice test attraverso il codice di seguito riportato:

<![CDATA[
<script type="text/javascript">
(function(){
//Il valore viene incrementato di un fattore 10 ad ogni test
var NUMBER_OF_ITEMS = 100;
var domEl = $('#list');
var ts = new Date();
for(var i = 0; i < NUMBER_OF_ITEMS; i++){
domEl.append('<li>'+i+'</li>');
}
var te = new Date();
var tt = te - ts;
console.log(tt);
})();
// ]]>

Il nostro contenitore di dati è una lista non ordinata che inizialmente è vuota e che poi provvederemo a popolare tramite un ciclo for. Di volta in volta andremo ad incrementare NUMBER_OF_ITEMS (numero di elementi che si vuole gestire) di un fattore 10. Prima e dopo l’esecuzione del ciclo prendiamo nota del tempo attuale la cui differenza permette di calcolare il tempo occorrente per l’esecuzione delle operazioni richieste. A seconda del browser e del sistema operativo otteniamo valori leggermente diversi ma coerenti con l’ordine di grandezza.

Riportiamo di seguito i risultati ottenuti impiegando il DOM come sistema di gestione dei dati:

Il tempo di esecuzione in questo caso è quello della creazione del DOM in memoria che non comprende anche il tempo di paint degli elementi, che in definitiva sembra rappresentare un vero collo di bottiglia dal momento in cui si devono gestire più di 10000 elementi. A ben considerare le cose i tempi di esecuzione del paint portano anche questo semplice esempio alla segnalazione di blocco da parte del browser a partire dalla soglia precedentemente dichiarata, soprattutto durante le operazioni di paint il sistema è bloccato l’utente che usa l’applicazione non può far altro che attendere.

Se in sostituzione della nostra lista non ordinata avessimo usato un semplice array per immagazzinare i dati le cose sarebbero andate decisamente meglio. Dapprima adattiamo il codice precedentemente usato poi riportiamo i nuovi risultati ottenuti.

<![CDATA[
<script type="text/javascript">
(function(){
//Il valore viene incrementato di un fattore 10 ad ogni test
var NUMBER_OF_ITEMS = 100;
var els = [];
var ts = new Date();
for(var i = 0; i < NUMBER_OF_ITEMS; i++){
els.push(i);
}
var te = new Date();
var tt = te - ts;
console.log(tt);
})();
// ]]>

Dando uno sguardo ai risultati ci rendiamo conto che in questo modo siamo in grado di gestire una mole di dati decisamente superiore così come il tempo impiegato per la manipolazione degli stessi che risulta di gran lunga inferiore, l’unico limite in questo caso è la memoria ram a disposizione.

In fine per concludere quando bisogna costruire applicazioni che richiedono un certo grado di performance e soprattutto se sitratta li applicazioni definite come “large scale application” bisogna controllare con parsimonia gli accessi al DOM e soprattutto evitare di usarlo come sistema per la manipolazione dei dati. In questi casi il consiglio è quello di usare lato cliente il ben noto pattern MVC appoggiandosi a quelle che sono le peculiarità messe a disposizione da HTML5 e dei vari framework MV* oggi presenti sul mercato.

P.S.
I risultati sono stati ottenuti eseguendo i test menzionati su un notebook acer aspire 5536 con ubuntu linux 13.04 e browser Chrome ver. 28