Object Pooling / Recycling
by Jeremy Easoz · in Torque Game Builder · 09/25/2008 (9:41 am) · 3 replies
Currently I have a bare bones ObjectPooling and Recycling ScriptGroup.
I'm having two problems with it currently.
1. Recycling Objects
I'm not really sure how to go about doing it.
function TObjectPool::pool_object(%this, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new t2dAnimatedSprite();
%this.add(%pooledObj);
}
}
After I use an object I just remove it from the pool and eventually the pool will run out.
2. Pooling
function TObjectPool::pool_object(%this, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new t2dAnimatedSprite();
%this.add(%pooledObj);
}
}
As you can see the above function will only pool a t2dAnimatedSprite().
Is there a way I can pass in an object type. Something like below (doesnt work)
function TObjectPool::pool_object(%this, %objType, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new %objType @ "();";
%this.add(%pooledObj);
}
}
I'm having two problems with it currently.
1. Recycling Objects
I'm not really sure how to go about doing it.
function TObjectPool::pool_object(%this, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new t2dAnimatedSprite();
%this.add(%pooledObj);
}
}
After I use an object I just remove it from the pool and eventually the pool will run out.
2. Pooling
function TObjectPool::pool_object(%this, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new t2dAnimatedSprite();
%this.add(%pooledObj);
}
}
As you can see the above function will only pool a t2dAnimatedSprite().
Is there a way I can pass in an object type. Something like below (doesnt work)
function TObjectPool::pool_object(%this, %objType, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new %objType @ "();";
%this.add(%pooledObj);
}
}
About the author
#2
Something like what Michael posted would allow you reuse some of the pooler-object code to easily create pools of different types though.
Interestingly enough, you might not actually need a factory method that gets call(ed). Something like this actually works.
%obj = new ("classType")();
09/25/2008 (11:57 am)
You can add object's of different types into a SimSet, but if you intermix them it will make getting one of the proper type out of the pool perform a lot worse since you need to loop through until you hit one of the type you want.Something like what Michael posted would allow you reuse some of the pooler-object code to easily create pools of different types though.
Interestingly enough, you might not actually need a factory method that gets call(ed). Something like this actually works.
%obj = new ("classType")();
#3
09/25/2008 (1:42 pm)
It really does. I didn't know that. Thanks James.
Torque Owner Michael Woerister
// Define a factory function for every object type function Create_t2dSceneObject() { return new t2dSceneObject(); } function Create_t2dStaticSprite() { return new t2dStaticSprite(); } function Create_t2dAnimatedSprite() { return new t2dAnimatedSprite(); } ... function Create_t2dTrigger() { return new t2dTrigger(); } // Define the pool class function ObjectPoolClass::PullObjectOut( %this ) { %freeList = %this.FreeList; %objectCount = %freeList.getCount(); if ( %objectCount != 0 ) { %object = %freeList.getObject( %objectCount - 1 ); %freeList.remove( %object ); return %object; } else { return call( %this.FactoryMethod ); } } function ObjectPoolClass::ThrowObjectBackIn( %this, %object ) { %this.FreeList.Add( %object ); // Comment this out in non-debug builds if ( %object.class !$= %this.ObjectClassName ) { error( "ObjectPoolClass::ThrowObjectBackIn() - Wrong Pool!" ); error( "Cannot throw" SPC %object.class SPC "in" SPC %this.ObjectClassName SPC "pool." ); } } function Create_ObjectPool( %objectClassName, %initialSize ) { %pool = new t2dSceneObject( %objectClassName @ "_ObjectPool" ) { class = "ObjectPoolClass"; }; %pool.FreeList = new SimSet(); %pool.ObjectClassName = %objectClassName; %pool.FactoryMethod = "Create_" @ %objectClassName; for ( %i = 0; %i < %initialSize; %i++ ) { %pool.FreeList.Add( call( %pool.FactoryMethod ) ); } return %pool; } function ObjectPoolClass::destroy( %this ) { while ( %this.FreeList.GetCount() > 0 ) { %object = %this.FreeList.GetObject( 0 ); %this.FreeList.Remove( %object ); %object.SafeDelete(); } %this.SafeDelete(); } // Then create the various pools ... $SceneObjectPool = Create_ObjectPool( "t2dSceneObject", 50 ); $StaticSpritePool = Create_ObjectPool( "t2dStaticSprite", 50 ); $AnimatedSpritePool = Create_ObjectPool( "t2dAnimatedSprite", 50 ); // ... and all other classes you need // ... and use them like this %someObject = $AnimatedSpritePool.PullObjectOut(); %someObject.blubb(); $AnimatedSpritePool.ThrowObjectBackIn( %someObject );Edit:
But as all of this runs in script, chances are not bad that it is actually slower than just using new and delete. I don't know. Heap fragmentation could still be an argument for using object pooling.
-Michael