do more with less

Dare una mano al Garbage Collector

Qualche tempo fa sono stato chiamato per aiutare un team di sviluppo a risolvere un problema su un'applicazione web che faceva uso dei Web Services di SharePoint. Il problema che il team riscontrava, in ambiente di produzione, nasceva in modo apparentemente random e rendeva la soluzione inutilizzabile in quanto bloccava IIS e richiedeva un reset dello stesso o, nei casi più fortunati, della sola applicazione.
Indagando con i ragazzi che avevano scritto il codice, abbiamo scoperto che il problema risiedeva nel mancato rilascio delle risorse che i Web Services di SharePoint richiedevano. E' bastato adottare la giusta politica di rilascio delle risorse e il problema è rientrato.

Ma perchè sto parlando di questo? Semplicemente perchè a volte, viziati dai molti automatismi che il framework ci mette a disposizione, ci dimentichiamo che il Garbage Collector non può fare miracoli e soprattutto non è in grado di deallocare memoria per risorse su cui non ha il controllo. Ma allora come si possono evitare questi problemi. La risposta è palese, con una corretta programmazione e quindi utilizzando gli eventuali metodi di Dispose o Close che gli oggetti ci mettono a disposizione. Certo questo presuppone che chi implementa gli oggetti, che utilizziamo nella nostra soluzione, esponga i metodi corretti per il rilascio delle risorse (nel caso dei servizi di SharePoint i metodi c'erano ma non erano stati utilizzati) e che noi ci impegnamo ad usare le tecniche migliori per garantire il rilascio delle risorse managed e non.
Un primo passo può essere quello di utilizzare lo statement using per tutti gli oggetti che implementano l'interfaccia IDisposable in modo da sfruttare il rilascio delle risorse al termine dell 'utilizzo delle stesse. Per esempio, ipotizzando di avere una classe MyClass che implementa l'interfaccia IDisposable, potremmo scrivere:

using (MyClass myClass = GetMyClass()) { myClass.DoSomething(); }

Ed all'interno della nostra classe, quale potrebbe essere il sistema migliore per implementare questa interfaccia? Potremmo adottare il Disposable Pattern così come indicato nell'articolo CLR Inside Out: Digging Into IDisposable di Shawn Farkas pubblicato su MSDN Magazine nel numero di Luglio 2007. Questo articolo aiuta a capire come utilizzare in modo appropriato le tecniche di rilascio delle risorse per evitare i comuni errori che si possono commettere in questi casi. Il risultato della disamina presentata nell'articolo è il seguente pattern:

public class DisposableClass : IDisposable { ~DisposableClass() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { //Pulizia di tutte le risorse gestite } //Pulizia di tutte le risorse native } }

Buona lettura e occhio alle risorse ;-)

Technorati tags: ,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Post correlati

Comments

Thursday, July 19, 2007 - 5:50 AM

Ciao Davide,
Il Finalizer (~DisposableClass) però andrebbe dichiarato solo se la classe alloca ed usa risorse unmanaged.

Alberto Dallagiacoma

Wednesday, September 12, 2007 - 4:53 PM

Prova a dare una letta all'articolo che cito nel post e forse tutto ti sarà più chiaro.

Davide

Thursday, October 25, 2007 - 5:53 AM

Ciao Davide,

pero, non è giustificabile che IIS vada in hang a causa di mancate chiamate al dispose() di oggetti scritti da terzi (nel caso SP). Se accade allora i componenti sono scritti male.

Infatti il dispose è fornito per dare al Dev la possibilità di rilasciare in modo deterministico le risorse (unmannaged). Se non viene chiamato allora, per oggetti non piu in uso, sara il GC a chiamarlo in maniera non deterministica oppure quando sara a corto di risorse. E' questo lo scopo dei IDispose.

Quindi prima di un hang dovrebbero scattare le opportune collection con consegunti chiamate dispose() e rilascio risorse.

Anni fa con 1.1 ho incontrato un memory leak a causa di mancate call al dispose() del controllo Menu winform pero non ho avuto il tempo per sottoporlo a MS.

In definitiva, avere dei resourse leak causati dalla mancata chiamata al dispose() viola principio di gestione automatica della memoria. Posso accettare problemi di perfomance e di esaurimento di risorse causa mio codice ma non di leaks causati da oggetti non piu refernziati di terze parti.







Al