Object Pool Design Pattern

Object Pool Design Pattern is pretty simple one. However, even here tutorials might fail. Let us take a look into a couple of examples:

  1. https://sourcemaking.com/design_patterns/object_pool
  2. https://www.geeksforgeeks.org/object-pool-design-pattern/

Both of these examples talk about performance like it should be the most important thing for the Object Pool while performance here is really important, but it is taken into consideration from a bit different angle. For instance, let us take a look into examples that Object Pool might actually be useful: Parallelization of jobs being performed. This is probably one and only class where Object Pool is actually useful. You take some tasks, you parallelize them across different threads, and you use Object Pool as a Factory or a provider for these objects. Creation and providing of these objects have nothing to do with performance. If you need something to do with performance in the object level, use Prototype for that, not an Object Pool.

In other words, it is correct to say that Object Pool might give some performance benefits. But it is retrieved through the pattern itself instead of through object creation. And finally, we should treat design patterns as an abstract way of designing our algorithms and systems. So, what actually does Object Pool give us? Well, it gives as a pretty centralized and easy to use API to get the objects we might want to get.

Another problem with the Object Pool is the example itself in the first tutorial. Why do we need always to compare design patterns with something which is completely unrelated to the Software Development? So we would be able to pretend that we understand what is this design pattern, yes? Why not trying to ACTUALLY understand and USE it instead of PRETEND? It would be much better for everyone.

So, let us take a look into the following code:

// First, we define the interface for generic Object Pool.
public interface IObjectPool<T>
{
    T Acquire();
 
    void Release(T node);
 
    void SetMaximumPoolSize(int size);
}
 
// Then, we define some Resource. Let us say it will be some node analysing website URL.
public interface IWebsiteURLAnalysisNode
{
    string Analyse(string url);
}
 
// And finally, we have the Object Pool itself:
public class AnalysisNodePool : IObjectPool<IWebsiteURLAnalysisNode>
{
    private static Semaphore _semaphore = new Semaphore(3, 3);
    private static AnalysisNodePool _instance = new AnalysisNodePool();
    private readonly Stack<IWebsiteURLAnalysisNode> _nodes = new Stack<IWebsiteURLAnalysisNode>();
    private readonly IWebsiteURLAnalysisNodeCreator _creator; // This would be initialized somehow, but for simplicity I am not doing this here.
 
    private AnalysisNodePool()
    {
    }
 
    // Would use some IoC Container (like Autofac), but for simplicity this is not bad. Just make sure not to include this into your real projects. Statics are not good if they can be replaced with non-statics.
 
    static AnalysisNodePool GetInstance()
    {
        return _instance;
    }
 
    public IWebsiteURLAnalysisNode Acquire()
    {
        _semaphore.WaitOne();
 
        if (_nodes.Count == 0)
        {
            return _creator.Create();
        }
 
        return _nodes.Pop();
    }
 
    public void Release(IWebsiteURLAnalysisNode node)
    {
        _nodes.Push(node);
 
        _semaphore.Release();
    }
 
    public void SetMaximumPoolSize(int size)
    {
        _semaphore = new Semaphore(size, size);
    }
}

As you can see, example is pretty real, since semaphore is used (to ensure maximum number of resources would get used at the same time). So, this is the example of how to actually use Object Pool design pattern. But why use it for crawler? Well, the reason here is that we know pretty well that number of sockets can be limited. Theoretically, it can be unlimited, but this would give no real benefit, thus adding abstraction to limit number of them in an easy manner is pretty nice way of thinking here. Still, not sure if this is very necessary for simple website crawler projects.

In other words, if you know that you have limited amount of resources that need to be shared among some other classes, then Object Pool Design pattern can be used. The main reason to use Object Pool is to provide some API of acquiring objects representing limited amount of resources, not efficiency as some examples like to say. Efficiency gains might be here, but this is not the reason.

Leave a Reply

Your email address will not be published. Required fields are marked *