diff options
Diffstat (limited to 'files/it/web/javascript/memory_management')
-rw-r--r-- | files/it/web/javascript/memory_management/index.html | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/files/it/web/javascript/memory_management/index.html b/files/it/web/javascript/memory_management/index.html new file mode 100644 index 0000000000..8fb72946cb --- /dev/null +++ b/files/it/web/javascript/memory_management/index.html @@ -0,0 +1,198 @@ +--- +title: Gestione della memoria +slug: Web/JavaScript/Memory_Management +translation_of: Web/JavaScript/Memory_Management +original_slug: Web/JavaScript/Gestione_della_Memoria +--- +<div>{{JsSidebar("Advanced")}}</div> + +<h2 id="Introduzione">Introduzione</h2> + +<p>Alcuni linguaggi di programmazione, come ad esempio C e C++, possiedono funzioni per la gestione della memoria a basso livello come <code>malloc()</code> e <code>free()</code>; in JavaScript l'allocazione e la de-allocazione della memoria (oggetti, stringhe, ecc.) avviene "automaticamente" grazie alla presenza del <em>Garbage Collection</em>. Il termine "automaticamente" è spesso fonte di confusione tra i programmatori JavaScript (e di altri linguaggi ad alto livello) poichè da l'impressione che si possa non preoccuparsi riguardo la gestione della memoria. Questo è un errore!</p> + +<h2 id="Ciclo_di_vita_della_memoria">Ciclo di vita della memoria</h2> + +<p>A prescindere dal linguaggio di programmazione, il ciclo di vita della memoria è pressappoco sempre lo stesso:</p> + +<ol> + <li>Allocazione della memoria necessaria</li> + <li>Utilizzo della memoria (scrittura, lettura)</li> + <li>Rilascio della memoria allocata quando non è più necessaria</li> +</ol> + +<p>I primi due punti sono espliciti in tutti i linguaggi; l'ultimo invece è esplicito nei linguaggi a basso livello, mentre il più delle volte implicito nei linguaggi ad alto livello come JavaScript.</p> + +<h3 id="Allocazione_in_JavaScript">Allocazione in JavaScript</h3> + +<h4 id="Inizializzazione_con_valore">Inizializzazione con valore</h4> + +<p>Per evitare che il programmatore debba allocare ogni variabile utilizzata, JavaScript lo fa contestualmente alla dichiarazione:</p> + +<pre class="brush: js">var n = 123; // alloca memoria per un numero +var s = "qwerty"; // alloca memoria per una stringa + +var o = { + a: 1, + b: null +}; // alloca memoria per un oggetto e i valori contenuti + +// (come un oggetto) alloca memoria per l'array e i valori contenuti +var a = [1, null, "abra"]; + +function f(a){ + return a + 2; +} // alloca una funzione (cioè un oggetto invocabile) + +// istruzioni più complesse anche allocano un oggetto +someElement.addEventListener('click', function(){ + someElement.style.backgroundColor = 'blue'; +}, false); +</pre> + +<h4 id="Allocazione_via_chiamata_di_funzione">Allocazione via chiamata di funzione</h4> + +<p>La chiamata di alcune funzioni risultano nell'allocazione di un oggetto, come nel seguente esempio:</p> + +<pre class="brush: js">var d = new Date(); +// alloca un DOM element +var e = document.createElement('div'); +</pre> + +<p>Alcuni metodi allocano nuovi valori od oggetti:</p> + +<pre class="brush: js">var s = "qwerty"; +var s2 = s.substr(0, 3); // s2 è una nuova stringa +// Dato che le stringhe sono valori immutabili, +// JavaScript può decidere di non allocare memoria per una nuova stringa, +// ma semplicemente di salvare il range [0, 3]. + +var a = ["ouais ouais", "nan nan"]; +var a2 = ["generation", "nan nan"]; +var a3 = a.concat(a2); +// Un nuovo array di 4 elementi, la concatenazione degli elementi di a e a2 +</pre> + +<h3 id="Utilizzo_dei_valori">Utilizzo dei valori</h3> + +<p>Usare i valori in sostanza significa accedere alla memoria allocata. Questo può essere fatto leggendo o scrivendo il valore di una variabile, di una proprietà di un oggetto, o anche semplicemente passando un argomento a una funzione.</p> + +<h3 id="Rilascio_della_memoria_quando_non_più_necessaria">Rilascio della memoria quando non più necessaria</h3> + +<p>La maggior parte dei problemi riguardo la gestione della memoria arrivano in questa fase; L'impresa più difficile è determinare quando "la memoria allocata non è più necessaria". Ciò si traduce per il programmatore in individuare dove, nel codice, questo pezzo di memoria non risulta più necessario, e quindi liberarlo.</p> + +<p>I linguaggi ad alto livello hanno una funzionalità chiamata "Garbage Collector" il cui compito è di seguire l'allocazione e l'uso della memoria così da determinare quando una porzione della memoria allocata non è più necessaria e liberarla automaticamente. Questo processo è un approssimazione dato che il problema generico di conoscere se una porzione di memoria serve o no è <a class="external external-icon" href="http://en.wikipedia.org/wiki/Decidability_%28logic%29">irrisolvibile</a> (non può essere risolto da un algoritmo).</p> + +<h2 id="Garbage_Collection">Garbage Collection</h2> + +<p>Partendo dal presupposto che il generico problema di sapere dove una determinata porzione di memoria "non serve più" è irrisolvibile, come conseguenza, l'implementazione dei garbege collection sono una restrizione della soluzione del problema generico. Questa sezione illustra le nozioni necessarie a capire il funzionamento dei principali algoritmi che implementano i garbage collection e le loro limitazioni.</p> + +<h3 id="Referenze">Referenze</h3> + +<p>L'idea principale su cui si basano gli algoritmi di garbage collection sono le <em>referenze</em>. Nel contesto della gestione della memoria, un oggetto è <em>referente</em> di un altro se può accedere a quest'ultimo (sia in modo implicito che esplicito). Ad esempio, un oggetto JavaScript è referente del suo <a href="/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">prototype</a> (referenza implicita) e ai valori delle sue proprietà (referenza esplicita).</p> + +<p>In questo contesto, il concetto di "oggetto" si estende a qualcosa di molto più ampio rispetto al tradizionale concetto di "oggetto JavaScript" e contiene function scopes (or the global lexical scope).</p> + +<h3 id="Reference-counting_garbage_collection">Reference-counting garbage collection</h3> + +<p>Quello qui descritto è l'algoritmo di garbage collection più semplice. Esso riduce il problema da "quando un oggetto non serve più" a "quando un oggetto non è più referenziato da nessun altro oggetto". Un oggetto è considerato garbage collectable (letteralmente, spazzatura da raccogliere) se nessun altro oggetto ha almeno una referenza ad esso.</p> + +<h4 id="Esempio">Esempio</h4> + +<pre class="brush: js">var o = { + a: { + b:2 + } +}; +// Alloca 2 oggetti. Il primo è referenziato dall'altro come sua proprietà. +// L'altro è referenziato dalla <s>dalla virtù di essere assegnato alla</s> variabile 'o'. +// Ovviamente, nessuno dei due può essere cancellato per liberare memoria + + +var o2 = o; // la variabile 'o2' è il secondo oggetto + // che referenzia lo stesso oggetto di 'o' +o = 1; // ora l'oggetto che originariamente era in 'o' ha un'unica referenza + // rappresentata dalla variabile 'o2' + +var oa = o2.a; // referenza alla proprietà 'a' dell'oggetto. + // Quest'oggetto ora ha 2 referenze: una come proprietà di 'o2' + // e una come variabile 'oa' + +o2 = "yo"; // L'oggetto che originariamente era in 'o' adesso non + // più alcuna referenza e può essere cancellato. + // Però la sua proprietà 'a' è ancora referenziata + // dall'oggetto 'oa', quindi non può essere ancora eliminato + +oa = null; // la proprietà 'a' del precedente oggetto adesso non ha + // alcuna referenza. Può essere cancellata. +</pre> + +<h4 id="Limitazione_cicli_di_referenze">Limitazione: cicli di referenze</h4> + +<p>Questo algotitmo ha una limitazione quando entra in un ciclo di referenze. Nell'esempio seguente sono creati due oggetti che si referenziano a vicenda, uno referenzia l'altro e viceversa, creando un ciclo di referenze (dipendenza ciclica). In questo modo ogni oggetto ha almento una referenza, l'algoritmo del reference-countig (ovvero quello che "conta" quante referenze ha un oggetto) da come risultato che nessuno dei due oggetti può essere cancellato (non sono garbage-collactable).</p> + +<pre class="brush: js">function f(){ + var o = {}; + var o2 = {}; + o.a = o2; // o referenzia o2 + o2.a = o; // o2 referenzia o + + return "qwerty"; +} + +f(); +// Two objects are created and reference one another thus creating a cycle. +// They will not get out of the function scope after the function call, so they +// are effectively useless and could be free'd. +// However, the reference-counting algorithm considers that since each of both +// object is referenced at least once, none can be garbage-collected. +</pre> + +<h4 id="Esempio_reale">Esempio reale</h4> + +<p>Internet Explorer 6 e 7 sono conosciuti per avere un <em>reference-counting garbage collector</em> per gli oggetti DOM. I cicli di referenze sono errori comuni che possono generare uno spreco di memoria (memory leaks).</p> + +<pre class="brush: js">var div; +window.onload = function(){ + div = document.getElementById("myDivElement"); + div<span style="font-size: 1rem;">.circularReference = div;</span> + div.lotsOfData = new Array(10000).join("*"); +}; +</pre> + +<p>Nell'esempio precedente, l'elemento "myDivElement" ha una referenza circolare con se stesso nella proprietà "circularReference". Se la proprietà non è esplicitamente rimossa o annullata, un <em>reference-counting garbage collector </em>avrà sempre almeno una referenza intatta che manterrà l'elemento in memoria anche se esso fosse rimosso dal DOM. Se un oggetto trattiene molta memoria e ha almeno una referenza (come illustrato nell'esempio precedente con la proprietà "lotsOfData") la memoria da esso occupata non sarà mai rilasciata.</p> + +<h3 id="L'algoritmo_mark-and-sweep">L'algoritmo mark-and-sweep</h3> + +<p>Questo algoritmo è il più famoso degli algoritmi di tracing; la tecnica del tracing è concettualmente molto semplice e si basa sulla definizione "quando un oggetto diventa irraggiungibile".</p> + +<p>Essa consiste nel prendere come riferimento gli oggetti root (indice dell'albero) e, partendo da essi, mediante una ricorsione, marcare (tramite un bit o una mappa distinta) tutti gli oggetti collegati tra loro da un riferimento. Al termine di questa operazione, gli oggetti raggiungibili saranno marcati mentre quelli non raggiungibili saranno eliminati.</p> + +<p>L'algoritmo mark-and-sweep (marca e butta via) si suddivide in due fasi: la prima fase (<em>mark</em>) nella quale l'algoritmo marca tutti gli oggetti che hanno almeno un riferimento attivo; nella seconda fase (<em>sweep</em>) nella quale tutti gli oggetti non marcati vengono liberati e la memoria viene restituita.</p> + +<p>A differenza della tecnica del reference counting il cui il costo dell'algoritmo è proporzionale all'ammontare del lavoro eseguito dal programma (ogni volta che si alloca/dealloca un oggetto bisogna creare-incrementare/decrementare il contatore), la tecnica del tracing è proporzionale alla dimensione della memoria ed è sicuramente più efficiente.</p> + +<h4 id="I_cicli_non_sono_più_un_problema">I cicli non sono più un problema</h4> + +<p>Nel primo esempio, dopo che la funzione ha restituito un risultato, i 2 oggetti non sono più referenziati da nessun altro oggetto raggiungibile dall'oggetto globale (root). Ne consegue che saranno irraggiungibili dal garbage collector e quindi eleminati.</p> + +<p>La stessa cosa accade con il secondo esempio. Una volta che il div e la sua variabile sono diventati irraggiungibili dalle radici, essi possono essere cancellati nonostante abbiano una referenza ciascuno.</p> + +<h4 id="Limitazione_gli_oggetti_devono_essere_esplicitamente_irragiungibili">Limitazione: gli oggetti devono essere esplicitamente irragiungibili</h4> + +<p>Sebbene sia marcata come una limitazione, è raramente raggiunta in pratica ed è anche il motivo per cui nessuno si preoccupa, di solito, dei garbage collector.</p> + +<blockquote> +<h4 id="Piccolo_appunto_italiano">Piccolo appunto italiano</h4> + +<p>Tutte le parole <s>tagliate</s> sono state tradotte letteralmente ma in modo che la frase non perda di significato.</p> + +<p dir="rtl">cit. Il traduttore</p> +</blockquote> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a class="external" href="http://www.ibm.com/developerworks/web/library/wa-memleak/">IBM article on "Memory leak patterns in JavaScript" (2007)</a></li> + <li><a class="external" href="http://msdn.microsoft.com/en-us/magazine/ff728624.aspx">Kangax article on how to register event handler and avoid memory leaks (2010)</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Performance" title="https://developer.mozilla.org/en-US/docs/Mozilla/Performance">PerformancC</a></li> +</ul> |