Object pool pattern

The object pool pattern is a software creational design pattern that uses a set of initialized objects kept ready to use – a "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 destroying it; this can be done manually or automatically.

Object pools are primarily used for performance: in some circumstances, object pools significantly improve performance. Object pools complicate object lifetime, as objects obtained from and returned to a pool are not actually created or destroyed at this time, and thus require care in implementation.

Description

When it is necessary to work with numerous 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. Closing a connection 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

Object pooling can offer a significant performance boost in situations where the cost of initializing a class instance is high and the rate of instantiation and destruction of a class is high – in this case objects can frequently be reused, and each reuse saves a significant amount of time. Object pooling requires resources – memory and possibly other resources, such as network sockets, and thus it is preferable that the number of instances in use at any one time is low, but this is not required.

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.[1] 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

Object pools can be implemented in an automated fashion in languages like C++ via smart pointers. In the constructor of the smart pointer, an object can be requested from the pool, and in the destructor of the smart pointer, the object can be released back to the pool. In garbage-collected languages, where there are no destructors (which are guaranteed to be called as part of a stack unwind), object pools must be implemented manually, by explicitly requesting an object from the factory and returning the object by calling a dispose method (as in the dispose pattern). Using a finalizer to do this is not a good idea, as there are usually no guarantees on when (or if) the finalizer will be run. Instead, "try ... finally" should be used to ensure that getting and releasing the object is exception-neutral.

Manual object pools are simple to implement, but harder to use, as they require manual memory management of pool objects.

Handling of empty pools

Object pools employ one of three strategies to handle a request when there are no spare objects in the pool.

  1. Fail to provide an object (and return an error to the client).
  2. Allocate a new object, thus increasing the size of the pool. Pools that do this usually allow you to set the high water mark (the maximum number of objects ever used).
  3. In a multithreaded environment, a pool may block the client until another thread returns an object to the pool.

Pitfalls

Care must be taken to ensure the state of the objects returned to the pool is reset back to a sensible state for the next use of the object, otherwise the object may be in a state unexpected by the client, which may cause it 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.

Stale state may not always be an issue; it becomes dangerous when it causes the object to behave unexpectedly. For example, an object representing authentication details may fail if the "successfully authenticated" flag is not reset before it is reused, since it indicates that a user is authenticated (possibly as someone else) when they are not. However, failing to reset a value used only for debugging, such as the identity of the last authentication server used, may pose no issues.

Inadequate resetting of objects can cause information leaks. Objects containing confidential data (e.g. a user's credit card numbers) must be cleared before being passed to new clients, otherwise, the data may be disclosed to an unauthorized party.

If the pool is used by multiple threads, it may need the means to prevent parallel threads from 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, 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 collectors; while the operator new needs only ten instructions, the classic new - delete 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.[1]

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.

// package pool
package pool

import (
	"errors"
	"log"
	"math/rand"
	"sync"
	"time"
)

const getResMaxTime = 3 * time.Second

var (
	ErrPoolNotExist  = errors.New("pool not exist")
	ErrGetResTimeout = errors.New("get resource time out")
)

//Resource
type Resource struct {
	resId int
}

//NewResource Simulate slow resource initialization creation
// (e.g., TCP connection, SSL symmetric key acquisition, auth authentication are time-consuming)
func NewResource(id int) *Resource {
	time.Sleep(500 * time.Millisecond)
	return &Resource{resId: id}
}

//Do Simulation resources are time consuming and random consumption is 0~400ms
func (r *Resource) Do(workId int) {
	time.Sleep(time.Duration(rand.Intn(5)) * 100 * time.Millisecond)
	log.Printf("using resource #%d finished work %d finish\n", r.resId, workId)
}

//Pool based on Go channel implementation, to avoid resource race state problem
type Pool chan *Resource

//New a resource pool of the specified size
// Resources are created concurrently to save resource initialization time
func New(size int) Pool {
	p := make(Pool, size)
	wg := new(sync.WaitGroup)
	wg.Add(size)
	for i := 0; i < size; i++ {
		go func(resId int) {
			p <- NewResource(resId)
			wg.Done()
		}(i)
	}
	wg.Wait()
	return p
}

//GetResource based on channel, resource race state is avoided and resource acquisition timeout is set for empty pool
func (p Pool) GetResource() (r *Resource, err error) {
	select {
	case r := <-p:
		return r, nil
	case <-time.After(getResMaxTime):
		return nil, ErrGetResTimeout
	}
}

//GiveBackResource returns resources to the resource pool
func (p Pool) GiveBackResource(r *Resource) error {
	if p == nil {
		return ErrPoolNotExist
	}
	p <- r
	return nil
}

// package main
package main

import (
	"github.com/tkstorm/go-design/creational/object-pool/pool"
	"log"
	"sync"
)

func main() {
	// Initialize a pool of five resources,
	// which can be adjusted to 1 or 10 to see the difference
	size := 5
	p := pool.New(size)

	// Invokes a resource to do the id job
	doWork := func(workId int, wg *sync.WaitGroup) {
		defer wg.Done()
		// Get the resource from the resource pool
		res, err := p.GetResource()
		if err != nil {
			log.Println(err)
			return
		}
		// Resources to return
		defer p.GiveBackResource(res)
		// Use resources to handle work
		res.Do(workId)
	}

	// Simulate 100 concurrent processes to get resources from the asset pool
	num := 100
	wg := new(sync.WaitGroup)
	wg.Add(num)
	for i := 0; i < num; i++ {
		go doWork(i, wg)
	}
	wg.Wait()
}

C#

In the .NET Base Class Library there are a few objects that implement this pattern. System.Threading.ThreadPool is configured to have a predefined number of threads to allocate. When the threads are returned, they are available for another computation. Thus, one can use threads without paying the cost of creation and disposal of threads.

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.

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;

    public DateTime CreatedAt => _createdAt;

    public string TempData { get; set; }
}

// 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()
    {
        lock (_available)
        {
            if (_available.Count != 0)
            {
                PooledObject po = _available[0];
                _inUse.Add(po);
                _available.RemoveAt(0);
                return po;
            }
            else
            {
                PooledObject po = new PooledObject();
                _inUse.Add(po);
                return po;
            }
        }
    }

    public static void ReleaseObject(PooledObject po)
    {
        CleanUp(po);

        lock (_available)
        {
            _available.Add(po);
            _inUse.Remove(po);
        }
    }

    private static void CleanUp(PooledObject po)
    {
        po.TempData = null;
    }
}

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.

Java

Java supports thread pooling via java.util.concurrent.ExecutorService and other related classes. The executor service has a certain number of "basic" threads that are never discarded. If all threads are busy, the service allocates the allowed number of extra threads that are later discarded if not used for the certain expiration time. If no more threads are allowed, the tasks can be placed in the queue. Finally, if this queue may get too long, it can be configured to suspend the requesting thread.

public class PooledObject {
	public String temp1;
	public String temp2;
	public String temp3;
	
	public String getTemp1() {
		return temp1;
	}
	public void setTemp1(String temp1) {
		this.temp1 = temp1;
	}
	public String getTemp2() {
		return temp2;
	}
	public void setTemp2(String temp2) {
		this.temp2 = temp2;
	}
	public String getTemp3() {
		return temp3;
	}
	public void setTemp3(String temp3) {
		this.temp3 = temp3;
	}
}
public class PooledObjectPool {
	private static long expTime = 6000;//6 seconds
	public static HashMap<PooledObject, Long> available = new HashMap<PooledObject, Long>();
	public static HashMap<PooledObject, Long> inUse = new HashMap<PooledObject, Long>();
	
	public synchronized static PooledObject getObject() {
		long now = System.currentTimeMillis();
		if (!available.isEmpty()) {
			for (Map.Entry<PooledObject, Long> entry : available.entrySet()) {
				if (now - entry.getValue() > expTime) { //object has expired
					popElement(available);
				} else {
					PooledObject po = popElement(available, entry.getKey());
					push(inUse, po, now); 
					return po;
				}
			}
		}

		// either no PooledObject is available or each has expired, so return a new one
		return createPooledObject(now);
	}	
	
	private synchronized static PooledObject createPooledObject(long now) {
		PooledObject po = new PooledObject();
		push(inUse, po, now);
		return po;
    }

	private synchronized static void push(HashMap<PooledObject, Long> map,
			PooledObject po, long now) {
		map.put(po, now);
	}

	public static void releaseObject(PooledObject po) {
		cleanUp(po);
		available.put(po, System.currentTimeMillis());
		inUse.remove(po);
	}
	
	private static PooledObject popElement(HashMap<PooledObject, Long> map) {
		 Map.Entry<PooledObject, Long> entry = map.entrySet().iterator().next();
		 PooledObject key= entry.getKey();
		 //Long value=entry.getValue();
		 map.remove(entry.getKey());
		 return key;
	}
	
	private static PooledObject popElement(HashMap<PooledObject, Long> map, PooledObject key) {
		map.remove(key);
		return key;
	}
	
	public static void cleanUp(PooledObject po) {
		po.setTemp1(null);
		po.setTemp2(null);
		po.setTemp3(null);
	}
}

See also

Notes

  1. ^ a b Goetz, Brian (2005-09-27). "Java theory and practice: Urban performance legends, revisited". IBM. IBM developerWorks. Archived from the original on 2012-02-14. Retrieved 2021-03-15.

References

Read other articles:

M. Satrio UtomoKadisopslatau ke-7PetahanaMulai menjabat 16 Januari 2023PendahuluJatmiko Adi Informasi pribadiLahir10 Desember 1973 (umur 49)Tarakan, Kalimantan UtaraKebangsaanIndonesiaSuami/istriNy. Reni Triwijayanti, S.E,Alma materAkademi Angkatan Udara (1995)Karier militerPihak IndonesiaDinas/cabang TNI Angkatan UdaraMasa dinas1995—sekarangPangkat Marsekal Pertama TNISatuanKorps Penerbang (Tempur)Sunting kotak info • L • B Marsekal Pertama TNI Mohamad ...

Western coastal region in Colombia Pacific/Chocó regionEcologyRealmNeotropicBiomeMarine, RainforestGeographyCountry ColombiaOceans or seasPacific OceanRiversAtrato, San Juan, PatíaClimate typeTropicalConservationGlobal 200Chocó Biogeographic The Pacific/Chocó region is one of the five major natural regions of Colombia. Ecologically, this region belongs entirely to the Chocó Biogeographic Region and is considered a biodiversity hotspot. It also has areas with the highest rainfall in ...

Romanian pornographic actress (born 1987) Alina PlugaruPlugaru on 14 May 2011Born (1987-12-18) 18 December 1987 (age 35)Vaslui, RomaniaOther namesEnrika Dolls, Enrika, Erika, Alina, Alina Blue, Crystal, Ellie, Eve, Nicole, SelenaHeight5 ft 7 in (1.70 m)Websitewww.alinaplugaru.ro Alina Plugaru (born 18 December 1987) is a Romanian entrepreneur and former pornographic film actress, who has been called in Romania The Queen of Porn.[1] She started acting in erotic...

JAM ProjectJAM Project di dalam Chibi Japan Expo dalam Paris, 2008Informasi latar belakangGenreAnison, VGM, rok, metal, popTahun aktif2000–sekarangLabelLantisSitus webhttp://www.jamjamsite.com/AnggotaHironobu KageyamaMasaaki EndohHiroshi KitadaniMasami OkuiYoshiki FukuyamaRicardo CruzMantan anggotaEizo SakamotoRica MatsumotoIchirou Mizuki JAM Project (Japan Animationsong Makers Project) adalah supergrup Jepang beraliran anison dan J-pop yang didirikan 19 Juli 2000 oleh vokalis lagu anime Ic...

1787 book by Mary Wollstonecraft First page of the first edition of Thoughts (1787) Thoughts on the education of daughters: with reflections on female conduct, in the more important duties of life is the first published work of the British feminist Mary Wollstonecraft. Published in 1787 by her friend Joseph Johnson, Thoughts is a conduct book that offers advice on female education to the emerging British middle class. Although dominated by considerations of morality and etiquette, the text al...

Resolusi 841Dewan Keamanan PBBHaitiTanggal16 Juni 1993Sidang no.3.238KodeS/RES/841 (Dokumen)TopikHaitiRingkasan hasil15 mendukungTidak ada menentangTidak ada abstainHasilDiadopsiKomposisi Dewan KeamananAnggota tetap Tiongkok Prancis Rusia Britania Raya Amerika SerikatAnggota tidak tetap Brasil Tanjung Verde Djibouti Spanyol Hungaria Jepang Maroko Selandia Baru Pakistan Venezuela Resolusi 841 Dewan Keamanan Pe...

Este artículo trata sobre el canal español. Para el canal peruano, véase Latina Televisión. Este artículo o sección necesita referencias que aparezcan en una publicación acreditada.Este aviso fue puesto el 1 de marzo de 2013. Telelatina Nombre público TelelatinaEslogan Un canal con identidad latinaProgramación GeneralPropietario Asociación Latina de Radio y TelevisiónPaís España EspañaInicio de transmisiones 10 de diciembre de 2009Personas clave Lester Burton (Director Pres...

Jekaterina Lobysjeva Persoonlijke informatie Volledige naam Jekaterina Lobysjeva Geboortedatum 13 maart 1985 Geboorteplaats Kolomna Geboorteland Sovjet-Unie Lengte 178 cm Gewicht 69 kg Sportieve informatie Specialisatie(s) 500 - 1500 meter Actieve jaren 2002-2017 Portaal    Schaatsen Jekaterina Aleksandrovna Lobysjeva (Russisch: Екатери́на Алекса́ндровна Ло́бышева) (Kolomna, 13 maart 1985) is een Russisch voormalige langebaanschaatsster die gespecial...

Sporting event delegationMauritius at theOlympicsIOC codeMRINOCMauritius Olympic CommitteeMedalsRanked 149th Gold 0 Silver 0 Bronze 1 Total 1 Summer appearances19841988199219962000200420082012201620202024 Mauritius first participated at the Olympic Games in 1984, and has sent athletes to compete in every Summer Olympic Games since then. The nation has never participated in the Winter Olympic Games. Mauritius also supported the American-led boycott of the 1980 Summer Olympics in Moscow. At the...

Brand of cybersecurity, privacy, performance and utility applications AVG TechnologiesTypeSubsidiaryFounded1991; 32 years ago (1991)FounderTomáš Hofer and Jan GritzbachFateMerged into Avast, brand still usedHeadquartersPrague, Czech RepublicArea servedWorldwideProductsSoftwareOwnerGen DigitalParentAvastWebsitewww.avg.com AVG Technologies is a brand of cybersecurity, privacy, performance and utility software applications for desktop computers and mobile devices developed by...

Premier of Quebec from 1882 to 1884 The HonourableJoseph-Alfred Mousseau6th Premier of QuebecIn officeJuly 29, 1882 – January 22, 1884MonarchVictoriaLieutenant GovernorThéodore RobitaillePreceded byJoseph-Adolphe ChapleauSucceeded byJohn Jones RossMLA for Jacques-CartierIn officeAugust 26, 1882 – January 22, 1884Preceded byNarcisse LecavalierSucceeded byArthur BoyerMember of the Canadian Parliamentfor BagotIn officeJanuary 22, 1874 – July 29, 1882Preceded...

Medical conditionKoenen's tumorOther namesKoenen's periungual fibroma[1] and Periungual fibroma[2]Koenen tumor in patient with tuberous sclerosis complexSpecialtyDermatology Koenen's tumor (KT), also commonly termed periungual angiofibroma,[1]: 668  is a subtype of the angiofibromas.[3] Angiofibromas are benign papule, nodule, and/or tumor lesions that are separated into various subtypes based primarily on the characteristic locations of the...

Overview of the use of artificial intelligence in healthcare X-ray of a hand, with automatic calculation of bone age by a computer software Part of a series onArtificial intelligence Major goals Artificial general intelligence Planning Computer vision General game playing Knowledge reasoning Machine learning Natural language processing Robotics AI safety Approaches Symbolic Deep learning Bayesian networks Evolutionary algorithms Situated approach Hybrid intelligent systems Systems integration...

Historic site in New South Wales, AustraliaWandiFront of Wandi facing the Hume HighwayLocation16501 Hume Highway, Narambulla Creek, 9.5 km south of, Marulan, Goulburn Mulwaree Council, New South Wales, AustraliaCoordinates34°44′32″S 149°54′46″E / 34.7422°S 149.9128°E / -34.7422; 149.9128Built1843– New South Wales Heritage RegisterOfficial nameThe Ben Hall Sites - Wandi; Plumb's Inn; Shelleys Flats; Douglass InnTypestate heritage (built)Designated8 Oct...

Cette page contient des caractères spéciaux ou non latins. Si certains caractères de cet article s’affichent mal (carrés vides, points d’interrogation, etc.), consultez la page d’aide Unicode. Fête des lanternes à Taipei. Fête des lanternes de Taiwan La fête des lanternes (元宵节 yuánxiāojié), où la lumière est reine, clôt le cycle des festivités du Nouvel an en Chine. Fête nocturne, on la nomme d'ailleurs parfois « petit Nouvel an » (xiaonian 小年)...

Çri Nata Rajasanagara Dyah Hayam WurukÇri Nata RajasanagaraÇri Nata WilwatiktaModern artist's impression of Hayam Wuruk4th Great King of MajapahitReign1350 – 1389PredecessorTribhuwana TunggadewīSuccessorBhra Hyang Wisesa Wikramawardhana2nd Prince of KahuripanReignca. 1334 – 1350PredecessorTribhuwana TunggadewīSuccessorTribhuwana TunggadewīBornDyah Hayam Wuruk1334Kingdom of MajapahitDied1389 (aged 54–55)Kingdom of MajapahitSpouseSudewi(Paduka Sori)Issue Kusumawardhani, 3rd Princess...

Pan American Games 2007 Logo Pan American Games 2007 Tuan rumah Rio de Janeiro Jumlah negara peserta 43 negara Jumlah atlet 5.500 atlet (perkiraan) Jumlah pertandingan 33 cabang olahraga Upacara pembukaan 13 Juli 2007 Upacara penutupan 29 Juli 2007 Stadion Stadion Maracanã Pan American Games 2007 (Pan American Games ke-15) diadakan di Rio de Janeiro, Brasil dari 13 Juli sampai 29 Juli 2007. Pemilihan tuan rumah PASO melakukan pemungutan suara untuk pemilihan tuan rumah Pan American Games 200...

Ilustrasi Rencana Longzhong. Rencana Longzhong adalah strategi yang dirancang oleh Zhuge Liang pada Zaman Tiga Negara (220–280) di Tiongkok. Zhuge Liang mengajukan rencana ini kepada Liu Bei, pemimpin perang yang kemudian menjadi pendiri negara Shu Han sekitar tahun 207 menjelang pembubaran Dinasti Han saat Liu Bei mengunjungi tempat tinggal Zhuge Liang di Longzhong (隆中), sebuah kawasan yang terletak di sebelah barat Xiangyang, Hubei.[1] Rencana Longzhong menjadi landasan pendir...

Australian cricketer For the Irish hurler, see Keith Carmody (hurler). Keith CarmodyCarmody in 1945Personal informationFull nameDouglas Keith CarmodyBorn(1919-02-16)16 February 1919Mosman, New South Wales, AustraliaDied21 October 1977(1977-10-21) (aged 58)Concord, New South Wales, AustraliaBattingRight-handedBowlingRight-arm mediumRoleMiddle-order batsmanDomestic team information YearsTeam1939/40–1946/47New South Wales1947/48–1955/56Western Australia Career statistics Competitio...

Taluk of Chengalpattu district Paddleboarding in Lake near Tirukalukundram Tirukalukundram taluk or Thirukalukundram taluk (Tamil: திருக்கழுகுன்றம் வட்டம்) is a taluk of Chengalpattu district of the Indian state of Tamil Nadu. The sacred town, Tirukalukundram is the present taluk headquarters. Formerly, the headquarters of the taluk was the town of Chengalpattu, which is a now a Taluk head of the newly formed namesake Taluk. Demographics According t...