Object pooling is a design pattern used to track and recycle expensive objects rather than recreating them whenever the application needs them. It consists of a pooling container, which holds reusable instances of objects. These are then doled out as needed and returned to the pool once their immediate purpose is fulfilled.
Repeated memory allocation in C# is
In this case, object pooling helps boost the performance of C# applications by keeping reusable instances of objects in a resource pool. This reduces the overhead of initialization, allocation, and disposal of objects.
The object pooling pattern is helpful in large applications, where object creation and destruction frequency is high. Moreover, if the objects are similar in size and represent a complex resource such as a network connection, using object pools to store and reuse them might be beneficial.
However, object pooling does not come without some downsides. Firstly, the memory size in a heap is fixed for each object. If the objects added to the pool vary in size, there's memory wastage and the risk of a large object overwriting the next one. Secondly, as our objects are not being cleared by a memory manager (or the garbage collector), the onus falls on the developer to clear the memory. Otherwise, unneeded objects may remain dormant for long, leading to potential performance overheads.
Object pooling consists of the following order of events:
The application requests an object instead of creating one. If the object is available in the pool, it is removed from the pool temporarily.
In case the object is unavailable, the pool creates a new object.
Once used, the object is returned to the pool, and its data is cleared for reuse.
The next time the application requires the same object, the now-empty object is taken from the pool.
The maximum number of objects allowed in a pool is up to the developer. There are several ways to implement a handling strategy in case this maximum allowance is reached:
Return null
or throw an exception
Increase the limit of objects in the pool
Wait for an object to be removed from the pool
To demonstrate object pooling, we will create a Student
class to show how the same objects can be reused.
We'll begin by creating a custom objectPool
class with the methods getObj()
and releaseObj()
. In this example, we will use the list collection in C#. However, queues can also be used for this purpose. The code is shown below:
public class objectPool<T> where T : new(){// list to hold the objectsprivate List<T> objectsList = new List<T>();//counter keeps track of the number of objects in the poolprivate int counter = 0;// max objects allowed in the poolprivate int maxObjects = 5;// returns the number of objects in the poolpublic int getCount(){return counter ;}// method to get object from the poolpublic T getObj(){// declare itemT objectItem;// check if pool has any objects// if yes, remove the first object and return it// also, decrease the countif (counter > 0){objectItem = objectsList[0] ;objectsList.RemoveAt(0) ;counter--;return objectItem;}// if the pool has no objects, create a new one and return itelse{T obj = new T();return obj;}}// method to return object to the pool// if counter is less than the max objects allowed, add object to the pool// also, increment counterpublic void releaseObj(T item){if(counter < maxObjects){objectsList.Add(item);counter++;}}}
The following is the explanation of the code for a custom object pool class:
Lines 4–8: We declare class variables. objectsList
is the pool in which we'll add our object and counter
is the number of objects in the pool at a point. maxObjects
is the maximum allowable objects in the pool, where the number is up to the programmer.
Lines 17–37: The getObject()
method first checks if the pool has any available objects. If it does, it removes the object from the pool and returns it. Otherwise, it creates a new object and returns that.
Lines 42–49: The releaseObj()
method checks if the number of objects in the pool is less than the maximum number of objects allowed. If true, it adds the released object to the pool and increments the counter.
Student
classNow that we've our generic object pool, let's create a simple Student
class to see our design in action. This class stores a student's first name and ID, with methods to get and set these variables.
// declaring a student class for demonstration purposesclass Student{private string firstName;private int studentID;public string getName(){return firstName ;}public void setName(string name){firstName = name ;}public int getID(){return studentID ;}public void setID(int ID){studentID = ID ;}}
With our sample class and object pool ready, let's put it together and see how objects are assigned. The following code demonstrates this:
using System;using System.Collections.Generic;using System.Collections;public class objectPool<T> where T : new(){// list to hold the objectsprivate List<T> objectsList = new List<T>();//counter keeps track of the number of objects in the poolprivate int counter = 0;// max objects allowed in the poolprivate int maxObjects = 5;// returns the number of objects in the poolpublic int getCount(){return counter ;}// method to get object from the poolpublic T getObj(){// declare itemT objectItem;// check if pool has any objects// if yes, remove the first object and return it// also, decrease the countif (counter > 0){objectItem = objectsList[0] ;objectsList.RemoveAt(0) ;counter--;return objectItem;}// if the pool has no objects, create a new one and return itelse{T obj = new T();return obj;}}// method to return object to the pool// if counter is less than the max objects allowed, add object to the pool// also, increment counterpublic void releaseObj(T item){if(counter < maxObjects){objectsList.Add(item);counter++;}}}// declaring a student class for demonstration purposesclass Student{private string firstName;private int studentID;public string getName(){return firstName ;}public void setName(string name){firstName = name ;}public int getID(){return studentID ;}public void setID(int ID){studentID = ID ;}}// this class executes the programclass Program{static void Main(string[] args){// declaring an object pool holding class Student objectsobjectPool<Student> objPool = new objectPool<Student>();Student obj = objPool.getObj();Console.WriteLine("First object assigned");objPool.releaseObj(obj);int count = objPool.getCount() ;Console.WriteLine("First object released back into the pool");Console.WriteLine("Current count of pool: " + count);Student obj2 = objPool.getObj() ;Console.WriteLine("Second object assigned");count = objPool.getCount() ;Console.WriteLine("Current count of pool: " + count);objPool.releaseObj(obj2);}}
The following is the explanation of the code to demonstrate how object pools work:
Line 90: We declare an object pool named objPool
to hold objects from the Student
class.
Line 92: We assign the first object, obj
. Since this is the first instance, the pool is empty; a new object is created and returned.
Line 94–97: We release obj
back into the pool and check the pool counter
. It returns obj
is successfully added back.
Lines 99–102: We create a second object, obj2
, and check the pool counter
. As expected, it returns
Free Resources