Invest in people before investing in tools

Il blog di Matteo Baglini
posts - 118, comments - 95, trackbacks - 697

[Spring.NET #19] Spring.Core, Object Pooling

Oggi parlerò delle funzionalità di Object Pooling esposte da Spring.NET, la spiegazione di questo pattern esula dallo scopo del post quindi per maggiori informazioni vi rimando a questo link: Object Pooling Pattern. Il namespace Spring.Pool espone due interfacce che permettono di creare un pool di qualsiasi oggetto:

  • IPoolableObjectFactory: definisce i metodi per la gestione del lifecycle dell'oggetto che sarà utilizzato nel pool.
  • IObjectPool: definisce i metodi per utilizzare e monitorizzare il pool di oggetti ed utilizza l'interfaccia sopra citata per istanziare gli oggetti del pool.

Inoltre Spring.NET tramite la classe SimplePool offre una semplice implementazione dell'interfaccia IObjectPool. Vediamo come sfruttare queste classi ed interfacce per creare un nostro pool. Come prima cosa aggiungiamo ad una Console Application una classe che rappresenterà l'oggetto "pesante" da creare:

   1: using System;
   2: using System.Threading;
   3:  
   4: namespace SpringSeries.Core.ObjectPooling
   5: {
   6:     public class BigObject : IDisposable
   7:     {
   8:         private Guid _id = Guid.Empty;
   9:  
  10:         public BigObject()
  11:         {
  12:             _id = Guid.NewGuid();
  13:             Thread.Sleep(1000);
  14:         }
  15:  
  16:         public string DoWork()
  17:         {
  18:             return String.Format("L'oggetto id: {0} sta lavorando.", _id);
  19:         }
  20:  
  21:         public void Dispose()
  22:         {
  23:             // dispose of the managed and unmanaged resources
  24:         }
  25:     }
  26: }

la classe è fittizia infatti nel costruttore utilizza il metodo Thread.Sleep per incrementare il tempo di creazione ed inoltre implementa l'interfaccia IDisposable per simulare la distruzione dell'oggetto, inoltre ho aggiunto un campo Id di tipo Guid per identificare l'oggetto. Procediamo creando una classe che implementa l'interfaccia IPoolableObjectFactory:

   1: using System;
   2: using Spring.Pool;
   3:  
   4: namespace SpringSeries.Core.ObjectPooling
   5: {
   6:     public class BigObjectPoolableFactory : IPoolableObjectFactory
   7:     {
   8:         #region IPoolableObjectFactory Members
   9:  
  10:         public void ActivateObject(object obj)
  11:         { }
  12:  
  13:         public void DestroyObject(object obj)
  14:         {
  15:             BigObject _bdo = obj as BigObject;
  16:             if (_bdo != null)
  17:                 _bdo.Dispose();
  18:         }
  19:  
  20:         public object MakeObject()
  21:         {
  22:             return new BigObject();
  23:         }
  24:  
  25:         public void PassivateObject(object obj)
  26:         { }
  27:  
  28:         public bool ValidateObject(object obj)
  29:         {
  30:             BigObject _bdo = obj as BigObject;
  31:             return (_bdo != null);
  32:         }
  33:  
  34:         #endregion
  35:     }
  36: }

implementiamo i metodi pricipali per creare (MakeObject), distruggere (DestroyObject) e validare (ValidateObject) l'oggeto. Nel metodo Main instanziamo un SimplePool passando nel costruttore la classe Factory ed il numero di istanze da creare, in fine effettuiamo una serie di richieste e rilasci di oggetti dal pool e verifichiamo in suo stato:

   1: using System;
   2: using Spring.Pool.Support;
   3:  
   4: namespace SpringSeries.Core.ObjectPooling
   5: {
   6:     class Program
   7:     {
   8:         static void Main(string[] args)
   9:         {
  10:             DateTime _time = DateTime.Now;            
  11:  
  12:             SimplePool _pool = new SimplePool(new BigObjectPoolableFactory(), 4);
  13:  
  14:             Console.WriteLine("Richiedo tre oggetti");
  15:             BigObject _bigobj1 = _pool.BorrowObject() as BigObject;
  16:             Console.WriteLine(_bigobj1.DoWork());
  17:             BigObject _bigobj2 = _pool.BorrowObject() as BigObject;
  18:             Console.WriteLine(_bigobj2.DoWork());
  19:             BigObject _bigobj3 = _pool.BorrowObject() as BigObject;
  20:             Console.WriteLine(_bigobj3.DoWork());
  21:  
  22:             Console.WriteLine("Oggetti disponibili: {0} in uso {1}", _pool.NumIdle, _pool.NumActive);
  23:  
  24:             Console.WriteLine("Rilascio due oggetti");
  25:             _pool.ReturnObject(_bigobj1);
  26:             _pool.ReturnObject(_bigobj3);
  27:  
  28:             Console.WriteLine("Oggetti disponibili: {0} in uso {1}", _pool.NumIdle, _pool.NumActive);
  29:  
  30:             Console.WriteLine("Richiedo altri tre oggetti");
  31:             BigObject _bigobj4 = _pool.BorrowObject() as BigObject;
  32:             Console.WriteLine(_bigobj4.DoWork());
  33:             BigObject _bigobj5 = _pool.BorrowObject() as BigObject;
  34:             Console.WriteLine(_bigobj5.DoWork());
  35:             BigObject _bigobj6 = _pool.BorrowObject() as BigObject;
  36:             Console.WriteLine(_bigobj6.DoWork());
  37:  
  38:             Console.WriteLine("Oggetti disponibili: {0} in uso {1}", _pool.NumIdle, _pool.NumActive);
  39:  
  40:             Console.WriteLine("Rilascio tutti gli oggetti.");
  41:             _pool.ReturnObject(_bigobj2);
  42:             _pool.ReturnObject(_bigobj4);
  43:             _pool.ReturnObject(_bigobj5);
  44:             _pool.ReturnObject(_bigobj6);
  45:  
  46:             Console.WriteLine("Oggetti disponibili: {0} in uso {1}", _pool.NumIdle, _pool.NumActive);
  47:  
  48:             Console.WriteLine("Tempo di utilizzo di 6 oggetti {0} secondi.", DateTime.Now.Subtract(_time).Seconds);
  49:  
  50:             Console.Read();
  51:         }
  52:     }
  53: }

grazie all' Id degli oggetti possiamo vedere come essi vengono reciclati nell richieste succcessive.

Technorati Tags:

Print | posted on giovedì 8 novembre 2007 19:23 | Filed Under [ .NET OpenSource Spring.NET ]

Powered by:
Powered By Subtext Powered By ASP.NET