Reuse memory

From Sidvind

Jump to: navigation, search

Contents

[edit] Description

It is commonly known that malloc/free and new/delete is expensive. In real-time applications we might have to create and destroy a lot of objects so this can become quite costly. What if we could reuse the object instead of deleting and later creating another? The idea is basically a static member function that creates or reuses the object and a method that discards it. This applies to c++ classes but the idea could be transformed to anything that allocates/deallocates memory. After reading this article you should hopefully be able to adopt this to your own code.

[edit] Object creation

Code: Class prototype

class Object {
	public:
		Object(int a);

		static Object* Object::construct(int a)
		void discard();

		void setA(int a);
	private:
		int _a;
		int _retainCount;
		static std::vector<Object*> _pool;
};
Code: The magic

Object* Object::construct(int a){
	if ( _pool.empty() ){
		return new Object(a);
	}
	
	Object* obj = _pool.back();
	_pool.pop_back();
	
	obj->setA(a);
			
	return obj;
}

When we need an object we call Object::construct(...) instead of new Object(...). If no objects exists in the pool a new object is created using regular new. However, if an object exists one is popped from the pool and is reconstructed.

[edit] Discard the object

Code: Basic discarding

void Object::discard(){
	_pool.push_back(this);

}

This does work but there is a lot of problems with this. The way I see it the largest problem is the pointer is still valid. It would also be a problem if the pointer would be stored in several places. This is a better version:

Code: A better way

void Object::discard(){
	_retainCount--;
	
	if ( _retainCount == 0 ){
		_pool.push_back(this);
	}
}

void discard(Object*& ptr){
	ptr->discard();
	ptr = 0;
}

To discard the object (the pointer at least) call discard(thePointer);. This way the pointer to the object can safely be passed along and copied as much as needed. As long as we increases the retaincount and makes sure we discards the pointer at some point of course. Also note that the last function is a function, not a method or member function. If you don't understand how this works read about retaincounting.

[edit] Performance

The following test created and destroyed 10000 objects 100 times using both methods. It alternated between the two methods. The test was performed on a AMD Athlon XP 2000+ running Gentoo linux.

Avarage of 100 tests (With gcc-4.1.1)
Compiler
optimization
New/DeleteReuse
None 1.678ms 2.256ms
-O1 1.436ms 0.150ms
-O2 1.431ms 0.137ms
-O3 1.439ms 0.086ms

As we can see it was actually slower without the compiler optimization but a LOT faster with it.

-->
Views
Personal tools
Navigation
Toolbox