c# .net object-pooling

c# - ¿Hay un conjunto de objetos de propósito general para.NET?



object-pooling (5)

Tengo una clase que es costosa de construir, en términos de tiempo y memoria. Me gustaría mantener un grupo de estas cosas y distribuirlas a pedido en varios subprocesos en el mismo proceso.

¿Hay un conjunto de objetos de propósito general que ya se haya probado y probado? (No quiero agrupar COM +).


¿Por qué no solo escribir un singleton que solo sirve como puerta de acceso a la matriz de objetos que se ha creado?

Cuando se entrega un objeto, luego retírelo de la lista disponible, póngalo en la lista extraída y luego, cuando se devuelva, inviértalo.

Al usar un singleton para esto, tiene una clase estática para que todo pueda llamar, y si la clase costosa es una clase interna del singleton, nada más puede crear la clase costosa, y puede controlar cuántos objetos crear fácilmente.


Extraído directamente de MSDN, aquí hay un ejemplo del uso de uno de los nuevos tipos de colección concurrente en .NET 4:

El siguiente ejemplo muestra cómo implementar un grupo de objetos con un System.Collections.Concurrent.ConcurrentBag<T> como su almacén de respaldo.

public class ObjectPool<T> { private ConcurrentBag<T> _objects; private Func<T> _objectGenerator; public ObjectPool(Func<T> objectGenerator) { if (objectGenerator == null) throw new ArgumentNullException("objectGenerator"); _objects = new ConcurrentBag<T>(); _objectGenerator = objectGenerator; } public T GetObject() { T item; if (_objects.TryTake(out item)) return item; return _objectGenerator(); } public void PutObject(T item) { _objects.Add(item); } }


La clase ObjectPool propuesta por 280Z28 se ve bastante bien. También podría considerar crear otra clase que implemente IDisposable y ajuste el valor de retorno de GetObject (). Esto asegurará que los objetos se devuelvan a su grupo y se lea bien:

class ObjectPoolReference<T> : IDisposable { public ObjectPool<T> Pool { get; private set; } public T Instance { get; private set; } public ObjectPoolReference(ObjectPool<T> pool, T instance) { Pool = pool; Instance = instance; } ~ObjectPoolReference() { Dispose(); } #region IDisposable Members private bool _Disposed = false; public void Dispose() { if (!_Disposed) { Pool.PutObject(Instance); _Disposed = true; } } #endregion } //instance of the pool ObjectPool<Foo> Pool; //"using" ensures the reference is disposed at the end of the block, releasing the object back to the pool using (var Ref = Pool.GetObject()) { Ref.Instance.DoSomething(); }


No Cheeso, no hay un conjunto de objetos general como este. Pero es una buena idea. Creo que esto sería bastante simple de desarrollar. La clave es hacer que funcione bien en un entorno de subprocesos.

Creo que este es un problema de diseño interesante. Por ejemplo, si esto necesita escalar en hardware de clase severa y le dará objetos a subprocesos individuales a menudo, entonces puede hacer esto:

  1. Mantener una sola piscina central de objetos.
  2. Mantenga una agrupación por subproceso (un caché) que se rellena cuando se llama por primera vez para un subproceso y cuando se vacía.

De esta manera, evitará la contención por subproceso para la mayoría de las solicitudes.

Diferentes condiciones operativas lo conducirían a un diseño diferente. Por ejemplo, si las asignaciones de objetos son raras o el número de subprocesos es bajo, entonces podría ser más simple tener un bloqueo alrededor de una colección. Esto no se escalará bien, pero en este caso, sería necesario.

Si diseña la clase o la interfaz correctamente, puede cambiar la implementación a lo largo del tiempo para manejar escenarios más complejos.