Jump to content

  • Log In with Google      Sign In   
  • Create Account


mychii

Member Since 19 Oct 2007
Offline Last Active Jul 25 2014 08:20 PM
-----

Topics I've Started

My Custom Memory Pool Seems Too Slow. Need Advice.

19 April 2014 - 06:31 AM

Hi guys,

 

So I'm warming up myself with C++ again, but my C++ isn't so much before anyway. As I am back, I try to get deeper in memory management.

 

I am currently trying to create my own generic memory pool for any object that inherits a parent class (I call it Object, which has a static memory pool attached to it). I need this memory pool so I could manually manage any child class that inherits Object.h at any time I, or the pool desire (I guess it's a garbage collector in the end; it is simply a pool).

So every time a class that inherits Object, it will have its new and delete overridden. The "new" will have a normal manual memory allocation, and "delete" simply stores the memory back to the pool in case it is needed again/not going back to free store, unless/until I flush them all either manually/automatically depends on the application needs.

Since children classes are always different, I make the memory pool to be generic per child class, therefore I use STL map. I do this to avoid memory corruption as every child class should have different size of memory required. This causes every memory allocation to check which class to find.

 

The memory pool works, but the performance is severe. I don't know whether it is the architecture, or STL overuse, or the code is too blunt, but I really need someone to give feedback on it. The performance is like 9x slower compare to default "new" when I test it with 100K iteration (1.8 sec compare to 0.2 sec) when allocating the memory. I even tried another test by filling the pool first before the test but it gets even slower! And I don't even include tracker for the pointers yet.

 

The thing is, I don't know if this is normal or not. But having it 9 times slower is somehow unacceptable for me. So again, please have a check if I miss something, maybe it's unsafe, the design sucks, or anything you find odd (it contains leaks, corruption, etc.). I need guidance. rolleyes.gif

 

Soo here's the code:

 

MemoryPool.h -> The memory pool!

/**
 * Generic stack-based memory pool.
 */

#ifndef MEMORY_POOL_H
#define MEMORY_POOL_H

#include <typeinfo>
#include <vector>
#include <map>
#include <string>

#include "Common.h"

namespace Engine
{
	using std::vector;
	using std::map;
	using std::string;

	template<typename T>
	class MemoryPool
	{
	public:
		MemoryPool();
		~MemoryPool();
		void* alloc(size_t size);
		void dealloc(void* ptr);

	private:
		map<string, vector<char*>> _pool = map<string, vector<char*>>();
	};

	template<typename T>
	MemoryPool<T>::MemoryPool()
	{
	}

	template<typename T>
	MemoryPool<T>::~MemoryPool()
	{
	}

	template<typename T>
	void* MemoryPool<T>::alloc(size_t size)
	{
		char* ptr;
		vector<char*> specificPool;
		std::map<string, vector<char*>>::const_iterator searcher = _pool.find(typeid(T).name());

		if (searcher != _pool.end())
		{
			specificPool = searcher->second;
		}
		else
		{
			_pool.insert(std::pair<string, vector<char*>>(typeid(T).name(), vector<char*>()));
			specificPool = _pool[typeid(T).name()];
		}

		// If there are idle pointers, then reuse one.
		if (specificPool.size() > 0)
		{
			ptr = specificPool.back();

			specificPool.pop_back();

			return ptr;
		}

		// If there is nothing to reuse, then allocate new one.
		ptr = new char[size];

		if (ptr != NULL)
		{
			return ptr;
		}

		// Return nullptr when no memory left.
		return nullptr;
	}

	template<typename T>
	void MemoryPool<T>::dealloc(void* ptr)
	{
		std::map<string, vector<char*>>::const_iterator searcher = _pool.find(typeid(T).name());

		if (searcher != _pool.end())
		{
			_pool[typeid(T).name()].push_back((char*)ptr);
		}
		else
		{
			cout << "ERROR: No pointer pointing at such object to deallocate!" << endl;
		}
	}
}

#endif

Object.h -> The parent class!

#ifndef OBJECT_H
#define OBJECT_H

#include <string>
#include <vector>

#include "MemoryPool.h"

namespace Engine
{
	using std::string;
	using std::vector;

	template<typename T>
	class Object
	{
	public:
		static MemoryPool<T> memoryPool;

	public:
		Object(string name);
		~Object();
		string& getName();
		void* operator new(size_t size);
		void operator delete(void* ptr);

		/**
		* Reset the object. Always put all cleaners here instead of destructors!
		*/
		virtual void reset() = 0;

	private:
		string _name;
	};

	template <typename T>
	MemoryPool<T> Object<T>::memoryPool = MemoryPool<T>();

	template <typename T>
	Object<T>::Object(string name) : _name(name)
	{
	}

	template <typename T>
	Object<T>::~Object()
	{
		_name.clear();
	}

	template <typename T>
	void* Object<T>::operator new(size_t size)
	{
		return memoryPool.alloc(size);
	}

	template <typename T>
	void Object<T>::operator delete(void* ptr)
	{
		memoryPool.dealloc(ptr);
	}

	template <typename T>
	string& Object<T>::getName()
	{
		return _name;
	}
}

#endif

Entity.h -> Sample usage of a child class that inherits Object.

#ifndef ENTITY_H
#define ENTITY_H

#include <vector>

#include "Common.h"
#include "Object.h"
#include "Component.h"

namespace Engine
{
	using std::vector;

	class Entity : public Object<Entity>
	{
	public:
		vector<Component*> components;

		Entity(string name);
		~Entity();
		void clearAllComponents();
		void reset();
	};
}

#endif

And here's how I benchmark them (without filling the pool first):

#include <iostream>
#include <ctime>

#include "Engine\Core\Entity.h"

using std::cout;
using std::endl;

using Engine::Entity;

/* Normal class */
class Car
{
public:
	Car() {}
	~Car() {}
	void getName() {}
};

int main()
{
	float startTime2 = (float)clock() / CLOCKS_PER_SEC;
	for (int iii = 0; iii < 100000; ++iii)
	{
		Entity* o = new Entity("Entity");
	}
	cout << (float)clock() / CLOCKS_PER_SEC - startTime2 << endl;
	

	float startTime = (float)clock() / CLOCKS_PER_SEC;
	for (int i = 0; i < 100000; ++i)
	{
		Car* car = new Car();
	}
	cout << (float)clock() / CLOCKS_PER_SEC - startTime << endl;

	return 0;
}

Note that there's Common.h header file. It contains only standard includes like cout and endl for debugging purposes, nothing else.

 

Thank you guys! wub.png


Shader Management for Lighting?

01 January 2014 - 09:28 AM

Hi,

 

I am currently learning to apply lighting to my application, but then I got confused on how I should scale it. I'm using WebGL and I'm learning from learningwebgl.com (which they say the same as NeHe OpenGL tutorial), and it only shows simple shader programs that every sample have one program with embedded lighting on it.

 

Say I have multiple lighting setup, like some point lights/spot lights, and I have multiple meshes with different materials. What should I do? make individual shader programs where you put colors/textures to meshes and then switch to lighting program? or always have every shader texts with those lights as default in it and simply make variable passes to enable them?

 

Also I am focusing on per-fragment lighting.

 

Thanks for the help!


Fire from Afar

31 December 2013 - 02:43 PM

Hi! It's been quite a while since I last compose and post on this side, let me start with a quite tense music.

 

The story is about a group of adventurers that find out their village burned down from afar after they are back from a dungeon.

 

Hope you like it! feedback/critics are much appreciated! laugh.png

 

https://soundcloud.com/mychiilist/fire-from-afar


Shaders (GLSL) in one file? Is it practical?

19 December 2013 - 12:04 PM

Hi, I'm currently playing around with WebGL, which of course, like OpenGL, deal with shaders. Since web always download files, I started to think that I better combine both vertex and fragment shaders into one file so I can just request that file as one shader program entirely.

 

Do you think it's practical? Is there any possibility that either shader importantly/needed to be shared among each other?

 

Thanks.


Does current graphics already provides feature-complete for photorealistic real-time re...

16 November 2013 - 11:54 PM

Hi, I don't know where to put this, since it's related to graphics programming and theory so I put it here.

 

I'm just wondering, what other features do we really need for photorealistic real-time rendering that may not be currently possible?

 

I mean, right now current graphics has offered many features that can give us photorealistic stuff possible in real-time, like real-time lighting, real-time shadows, bokeh, bloom, HDR, tessellation, and more, all in one, running in current high-end graphic cards. It was totally not like back in 2000 where things like real-time shadows and post-processing were new and amazing, also hackish light maps, etc..

 

Any thoughts?

 

Thanks!


PARTNERS