Object pool pattern: Difference between revisions

Content deleted Content added
See also: add portal
 
(23 intermediate revisions by 19 users not shown)
Line 1:
{{Short description|Software creational design pattern}}
{{for|the article about a general pool|Pool (computer science)}}
{{citestyle|date=March 2012}}
 
The '''object pool pattern''' is a software [[creational pattern|creational design pattern]] that uses a set of initialized [[Object (computer science)|objects]] kept ready to use – a "[[Pool (computer science)|pool]]" – rather than allocating and destroying them on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished, it returns the object to the pool rather than [[object destruction|destroying it]]; this can be done manually or automatically.
 
Line 7 ⟶ 6:
 
== Description ==
When it is necessary to work with a large number ofnumerous objects that are particularly expensive to instantiate and each object is only needed for a short period of time, the performance of an entire application may be adversely affected. An object pool design pattern may be deemed desirable in cases such as these.
 
The object pool design pattern creates a set of objects that may be reused. When a new object is needed, it is requested from the pool. If a previously prepared object is available, it is returned immediately, avoiding the instantiation cost. If no objects are present in the pool, a new item is created and returned. When the object has been used and is no longer needed, it is returned to the pool, allowing it to be used again in the future without repeating the computationally expensive instantiation process. It is important to note that once an object has been used and returned, existing references will become invalid.
 
In some object pools the resources are limited, so a maximum number of objects is specified. If this number is reached and a new item is requested, an exception may be thrown, or the thread will be blocked until an object is released back into the pool.
 
The object pool design pattern is used in several places in the standard classes of the .NET Framework. One example is the .NET Framework Data Provider for SQL Server. As SQL Server database connections can be slow to create, a pool of connections is maintained. When you closeClosing a connection it does not actually relinquish the link to SQL Server. Instead, the connection is held in a pool, from which it can be retrieved when requesting a new connection. This substantially increases the speed of making connections.
 
== Benefits ==
Line 20 ⟶ 19:
The pooled object is obtained in predictable time when creation of the new objects (especially over network) may take variable time. These benefits are mostly true for objects that are expensive with respect to time, such as database connections, socket connections, threads and large graphic objects like fonts or bitmaps.
 
In other situations, simple object pooling (that hold no external resources, but only occupy memory) may not be efficient and could decrease performance.<ref name="urban">{{cite web|last1=Goetz|first1=Brian|date=2005-09-27|title=Java theory and practice: Urban performance legends, revisited|url=http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html|url-status=dead|archive-url=https://web.archive.org/web/20120214195433/http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html|archive-date=2012-02-14|access-date=2021-03-15|website=[[IBM]]|publisher=IBM developerWorks}}</ref> In case of simple memory pooling, the [[slab allocation]] memory management technique is more suited, as the only goal is to minimize the cost of memory allocation and deallocation by reducing fragmentation.
| url = http://www.ibm.com/
| title = Java theory and practice: Urban performance legends, revisited
| last1 = Goetz
| first1 = Brian
| date = 2005-09-27
| work =
| publisher = IBM developerWorks
| archiveurl = http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html
| archivedate = 2005-09-27
| quote =
| accessdate = 2012-08-28
}}</ref> In case of simple memory pooling, the [[slab allocation]] memory management technique is more suited, as the only goal is to minimize the cost of memory allocation and deallocation by reducing fragmentation.
 
== Implementation ==
Line 49 ⟶ 36:
== Pitfalls ==
 
WhenCare writing an object pool, the programmer has tomust be carefultaken to make sureensure the state of the objects returned to the pool is reset back to a sensible state for the next use of the object., If this is not observed,otherwise the object will oftenmay be in somea state that was unexpected by the client, program andwhich may cause the client programit to fail. The pool is responsible for resetting the objects, not the clients. Object pools full of objects with dangerously stale state are sometimes called object cesspools and regarded as an [[anti-pattern]].
 
The presence of staleStale state ismay not always be an issue; it becomes dangerous when the presence of stale stateit causes the object to behave differentlyunexpectedly. For example, an object that representsrepresenting authentication details may breakfail if the "successfully authenticated" flag is not reset before it is passed outreused, since it will indicateindicates that a user is correctly authenticated (possibly as someone else) when they haven'tare yet attempted to authenticatenot. However, it will work just fine if you failfailing to reset somea value only used only for debugging, such as the identity of the last authentication server used, may pose no issues.
 
Inadequate resetting of objects may alsocan cause an information leakleaks. If anObjects object containscontaining confidential data (e.g. a user's credit card numbers) thatmust isn'tbe cleared before the object isbeing passed to a new clientclients, aotherwise, maliciousthe or buggy clientdata may disclosebe the datadisclosed to an unauthorized party.
 
If the pool is used by multiple threads, it may need the means to prevent parallel threads from grabbing and trying to reuse the same object in parallel. This is not necessary if the pooled objects are immutable or otherwise thread-safe.
 
== Criticism ==
Some publications do not recommend using object pooling with certain languages, such as [[Java (programming language)|Java]], especially for objects that only use memory and hold no external resources (such as connections to database). Opponents usually say that object allocation is relatively fast in modern languages with [[Garbage collection (computer science)|garbage collectors]]; while the operator <refcode>new</code>{{cite webneeds only ten instructions, the classic <code>new</code> - <code>delete</code> pair found in pooling designs requires hundreds of them as it does more complex work. Also, most garbage collectors scan "live" object references, and not the memory that these objects use for their content. This means that any number of "dead" objects without references can be discarded with little cost. In contrast, keeping a large number of "live" but unused objects increases the duration of garbage collection.<ref name="urban" />
| url = http://www.ibm.com/
| title = Java theory and practice: Garbage collection in the HotSpot JVM
| last1 = Goetz
| first1 = Brian
| date = 2005-09-27
| work =
| publisher = IBM developerWorks
| archiveurl = http://www.ibm.com/developerworks/java/library/j-jtp11253/
| archivedate = 2003-11-25
| quote =
| accessdate = 2012-08-28
}}</ref> Opponents usually say that object allocation is relatively fast in modern languages with [[Garbage collection (computer science)|garbage collectors]]; while the operator <code>new</code> needs only ten instructions, the classic <code>new</code> - <code>delete</code> pair found in pooling designs requires hundreds of them as it does more complex work. Also, most garbage collectors scan "live" object references, and not the memory that these objects use for their content. This means that any number of "dead" objects without references can be discarded with little cost. In contrast, keeping a large number of "live" but unused objects increases the duration of garbage collection.<ref name="urban" />
 
== Examples ==
=== Go ===
The following Go code initializes a resource pool of a specified size (concurrent initialization) to avoid resource race issues through channels, and in the case of an empty pool, sets timeout processing to prevent clients from waiting too long.
resource pool model is a kind of resource advance, resource reuse, suitable for stable business processing mode:
- object resource reuse: the object pool pattern is useful when objects are heavily initialized.
- suitable for stable business: if requirements peak rather than stable requirements, the overhead may outweigh the benefits of object pooling.
- resource advances: since objects are pre-initialized, they have a positive impact on performance.
 
<sourcesyntaxhighlight lang=Go>
// package pool
package pool
Line 193 ⟶ 165:
wg.Wait()
}
</syntaxhighlight>
</source>
 
=== C# ===
Line 199 ⟶ 171:
 
The following shows the basic code of the object pool design pattern implemented using C#. For brevity the properties of the classes are declared using C# 3.0 automatically implemented property syntax. These could be replaced with full property definitions for earlier versions of the language. Pool is shown as a static class, as it's unusual for multiple pools to be required. However, it's equally acceptable to use instance classes for object pools.
<sourcesyntaxhighlight lang="csharp">
namespace DesignPattern.Objectpool ;
 
// The PooledObject class is the type that is expensive or slow to instantiate,
// or that has limited availability, so is to be held in the object pool.
public class PooledObject
{
private DateTime _createdAt = DateTime.Now;
// The PooledObject class is the type that is expensive or slow to instantiate,
// or that has limited availability, so is to be held in the object pool.
public class PooledObject
{
DateTime _createdAt = DateTime.Now;
public DateTime CreatedAt
{
get { return _createdAt; }
}
public string TempData { get; set; }
}
 
public DateTime CreatedAt => _createdAt;
// The Pool class is the most important class in the object pool design pattern. It controls access to the
 
// pooled objects, maintaining a list of available objects and a collection of objects that have already been
public string TempData { get; set; }
// requested from the pool and are still in use. The pool also ensures that objects that have been released
}
// are returned to a suitable state, ready for the next time they are requested.
 
public static class Pool
// The Pool class controls access to the pooled objects. It maintains a list of available objects and a
// collection of objects that have been obtained from the pool and are in use. The pool ensures that released objects
// are returned to a suitable state, ready for reuse.
public static class Pool
{
private static List<PooledObject> _available = new List<PooledObject>();
private static List<PooledObject> _inUse = new List<PooledObject>();
 
public static PooledObject GetObject()
{
private static List<PooledObject>lock (_available = new List<PooledObject>();
private static List<PooledObject> _inUse = new List<PooledObject>();
public static PooledObject GetObject()
{
lockif (_available.Count != 0)
{
ifPooledObject (_available.Countpo != _available[0)];
{_inUse.Add(po);
PooledObject po = _available[.RemoveAt(0]);
return _inUse.Add(po);
_available.RemoveAt(0);
return po;
}
else
{
PooledObject po = new PooledObject();
_inUse.Add(po);
return po;
}
}
} else
public static void ReleaseObject(PooledObject po)
{
CleanUp(po);
lock (_available)
{
_available.Add(PooledObject po = new PooledObject();
_inUse.RemoveAdd(po);
return po;
}
}
}
 
private static void CleanUp(PooledObject po)
public static void ReleaseObject(PooledObject po)
{
CleanUp(po);
 
lock (_available)
{
po_available.TempData = nullAdd(po);
_inUse.Remove(po);
}
}
 
private static void CleanUp(PooledObject po)
{
po.TempData = null;
}
}
</syntaxhighlight>
</source>
In the code above, the PooledObject has properties for the time it was created, and another, that can be modified by the client, that is reset when the PooledObject is released back to the pool. Shown is the clean-up process, on release of an object, ensuring it is in a valid state before it can be requested from the pool again.
In the code above, the PooledObject includes two properties that are not shown in the UML diagram. One holds
the time at which the object was first created. The other holds a string that can be modified by the client
but that is reset when the PooledObject is released back to the pool. This shows the clean-up process on release
of an object that ensures it is in a valid state before it can be requested from the pool again.
 
=== Java ===
Line 294 ⟶ 258:
public void setTemp3(String temp3) {
this.temp3 = temp3;
}
}
 
</syntaxhighlight><syntaxhighlight lang="java">
Line 324 ⟶ 289:
push(inUse, po, now);
return po;
}
 
private synchronized static void push(HashMap<PooledObject, Long> map,
Line 360 ⟶ 325:
 
== See also ==
{{Portal|Computer programming}}
* [[Connection pool]]
* [[Free list]]
* [[Slab allocation]]
 
==ReferencesNotes==
{{reflist|30em}}
 
==References==
{{refbegin}}
*{{cite conference
Line 372 ⟶ 340:
|author2=Prashant Jain
| title = Pooling Pattern
| booktitlebook-title = EuroPLoP 2002
| place = Germany
| date = 2002-07-04
| url = http://www.kircher-schwanninger.de/michael/publications/Pooling.pdf
| accessdateaccess-date = 2007-06-09 }}
* {{Cite book | isbn = 978-1-4302-4458-5 | title = Pro .NET Performance: Optimize Your C# Applications | last1 = Goldshtein | first1 = Sasha | last2 = Zurbalev | first2 = Dima | last3 = Flatow | first3 = Ido | year = 2012 | publisher = Apress | url = http://www.apress.com/9781430244585 | pages = }}
{{refend}}
 
Line 392 ⟶ 360:
[[Category:Software design patterns]]
[[Category:Software optimization]]
[[Category:Articles with example C Sharp code]]
[[Category:Articles with example Java code]]