CEGUI+Custom memory allocator
Moderators: CEGUI MVP, CEGUI Team
Re: CEGUI+Custom memory allocator
Just a note here, I am playing with something related but not the same as e3d_alive2... I am trying to delegate CEGUI mem allocation to external libraries, not support alternative allocators. My goal is to delegate to Ogre's nedmalloc implementation.
Initial patch: http://harcov.czenet.com/kulik/CEGUI/custom_allocators.patch
Initial patch: http://harcov.czenet.com/kulik/CEGUI/custom_allocators.patch
Re: CEGUI+Custom memory allocator
Posting to show support: I favour nedmalloc because it is highly efficient and with very small footprint, and from a quick look at your patch it seems like a well-designed solution (caveat: I am not well versed in the CEGUI internals!).
Re: CEGUI+Custom memory allocator
I glanced over the OGRE custom memory management, as well as Kulik's patch, and I think that this approach is very well conceived. It gives both the library and client the leverage to implement memory schemes according to their needs via both inherited and specified allocators. I do have one question though: should the client be able to re-define the inherited allocators? Eg these:
I also noticed an oddity in the patch on line 741: the destroyWindow() implementation was changed from delete window; too new window;?
Code: Select all
+typedef MemoryStdAllocator AnimationAllocator;
+typedef MemoryStdAllocator AnimationInstanceAllocator;
+typedef MemoryStdAllocator EventAllocator;
+typedef MemoryStdAllocator FontAllocator;
+typedef MemoryStdAllocator GeometryBufferAllocator;
+typedef MemoryStdAllocator SingletonAllocator;
+typedef MemoryStdAllocator StringAllocator;
+typedef MemoryStdAllocator TextureAllocator;
+typedef MemoryStdAllocator WindowAllocator;
I also noticed an oddity in the patch on line 741: the destroyWindow() implementation was changed from delete window; too new window;?
Code: Select all
Index: include/CEGUIWindowFactory.h
===================================================================
--- include/CEGUIWindowFactory.h (revision 2657)
+++ include/CEGUIWindowFactory.h (working copy)
@@ -60,11 +60,11 @@
T ## Factory() : WindowFactory( T::WidgetTypeName ) {}\
Window* createWindow(const String& name)\
{\
- return new T (d_type, name);\
+ return new T(d_type, name);\
}\
void destroyWindow(Window* window)\
{\
- delete window;\
+ new window;\
}\
};\
T ## Factory& get ## T ## Factory();
If somebody helps you by replying to your thread, upvote him/her as a thanks! Make sure to include your CEGUI.log and everything you tried when posting! And remember that we are not magicians!
Re: CEGUI+Custom memory allocator
Yeah client should be able to redefine the typedefs so different allocators can be used for various classes.
The oddity is already fixed, CE spotted it too. Thanks for the feedback! I will post a new version of the patch soon.
Leaked rumours:
CEGUI startup without custom allocators: 303639 msec
CEGUI startup with malloc allocator: 310553 msec
CEGUI startup with Ogre's nedmalloc: 176020 msec
The speedup is pretty impressive. Seems almost too good to be true to me. The biggest benefit is at startup/shutdown. CEGUI doesn't alloc/dealloc much during runtime.
The oddity is already fixed, CE spotted it too. Thanks for the feedback! I will post a new version of the patch soon.
Leaked rumours:
![Wink :wink:](./images/smilies/icon_wink.gif)
CEGUI startup without custom allocators: 303639 msec
CEGUI startup with malloc allocator: 310553 msec
CEGUI startup with Ogre's nedmalloc: 176020 msec
The speedup is pretty impressive. Seems almost too good to be true to me. The biggest benefit is at startup/shutdown. CEGUI doesn't alloc/dealloc much during runtime.
Re: CEGUI+Custom memory allocator
Almost 45% decrease is pretty impressive. I wonder if users who use a lot of dynamic windows would see similar gains. I also wonder if nedmalloc (http://www.nedprod.com/programs/portable/nedmalloc/) should be the default allocator, or at least an easily configurable option. It appears to be a very good library.
If somebody helps you by replying to your thread, upvote him/her as a thanks! Make sure to include your CEGUI.log and everything you tried when posting! And remember that we are not magicians!
Re: CEGUI+Custom memory allocator
I think I will post some code on how to integrate CEGUI with nedmalloc, Ogre and perhaps some other libraries on Wiki, not sure if bundling these with CEGUI is the right thing. Remember that this is all experimental stuff, highly flammable. I think it should get released as disabled by default and if it works for most people, this could change but definitely not sooner
I am currently walking through classes, marking which ones should be custom allocated and which ones should not.
![Wink :wink:](./images/smilies/icon_wink.gif)
I am currently walking through classes, marking which ones should be custom allocated and which ones should not.
Re: CEGUI+Custom memory allocator
Indeed. I was thinking something along the xml and image codec options we have now...default to standard new/malloc, with an easily configurable option to use nedmalloc, as well as ogre memory managers.
If somebody helps you by replying to your thread, upvote him/her as a thanks! Make sure to include your CEGUI.log and everything you tried when posting! And remember that we are not magicians!
Re: CEGUI+Custom memory allocator
From my experiences with nedmalloc, when you get the code stable it should probably be the default option. Nedmalloc seems very robust and highly efficient, it is the default iirc in OGRE, and seems to be increasingly used used in both open source and big-budget commercial software so any errors should have been hammered out of it by now. Also, most development is done in Win32, and by Ned's measurements nedmalloc is about seven times faster than the standard Win32 allocator, so it seems a natural feature to a MS Windows-heavy user base.
Re: CEGUI+Custom memory allocator
Just some nitpicking about the macros in Kulik's patch... ![Smile :)](./images/smilies/icon_smile.gif)
- delete[] operator destroys the elements in reverse order, so I think just for consistency CEGUI_DELETE_ARRAY_T should do the same.
- Bad things will happen if someone uses CEGUI_DELETE_T or CEGUI_DELETE_ARRAY_T inside an if...else statement. To prevent the macros from "stealing" the following else keyword they need to be enclosed in a block.
Here's how I would do these:
What it comes to including nedmalloc with CEGUI and possibly having it enabled by default, I'm actually for it. That way even those who don't care or don't understand about allocators can still get the benefits. If the patch is just to allow the replacement of the allocator, then to be honest I don't see it as quite as useful. Because the people who do care about memory management, can already use a custom allocator somewhat easily by overloading the new operator globally. (Though I admit not everyone likes doing that.)
![Smile :)](./images/smilies/icon_smile.gif)
- delete[] operator destroys the elements in reverse order, so I think just for consistency CEGUI_DELETE_ARRAY_T should do the same.
- Bad things will happen if someone uses CEGUI_DELETE_T or CEGUI_DELETE_ARRAY_T inside an if...else statement. To prevent the macros from "stealing" the following else keyword they need to be enclosed in a block.
Here's how I would do these:
Code: Select all
# define CEGUI_DELETE_T(ptr, T, Allocator) do{ if(ptr){(ptr)->~T(); Allocator::deallocateBytes((void*)ptr, __FILE__, __LINE__, __FUNCTION__);} }while(0)
# define CEGUI_DELETE_ARRAY_T(ptr, T, count, Allocator) do{ if(ptr){for (size_t b = count; b-- > 0;) { (ptr)[b].~T();} Allocator::deallocateBytes((void*)ptr, __FILE__, __LINE__, __FUNCTION__);} }while(0)
Code: Select all
# define CEGUI_DELETE_T(ptr, T, Allocator) do{ if(ptr){(ptr)->~T(); Allocator::deallocateBytes((void*)ptr);} }while(0)
# define CEGUI_DELETE_ARRAY_T(ptr, T, count, Allocator) do{ if(ptr){for (size_t b = count; b-- > 0;) { (ptr)[b].~T();} Allocator::deallocateBytes((void*)ptr);} }while(0)
What it comes to including nedmalloc with CEGUI and possibly having it enabled by default, I'm actually for it. That way even those who don't care or don't understand about allocators can still get the benefits. If the patch is just to allow the replacement of the allocator, then to be honest I don't see it as quite as useful. Because the people who do care about memory management, can already use a custom allocator somewhat easily by overloading the new operator globally. (Though I admit not everyone likes doing that.)
Re: CEGUI+Custom memory allocator
Thanks for the nitpicking Timo
I have actually run into such problems and have solved them by scoping the macros with just {}, does this approach (do {} while(0)) have any advantages over scoping? Thanks..
Whether nedmalloc will be included in the distribution is still undecided, binary CEGUI SDKs will definitely be without allocators, you will have to compile CEGUI yourself to get them... However I guess I could include some wrappers to make it easier to use nedmalloc and Ogre.
![Wink ;-)](./images/smilies/icon_wink.gif)
Whether nedmalloc will be included in the distribution is still undecided, binary CEGUI SDKs will definitely be without allocators, you will have to compile CEGUI yourself to get them... However I guess I could include some wrappers to make it easier to use nedmalloc and Ogre.
Re: CEGUI+Custom memory allocator
Kulik wrote:Thanks for the nitpicking TimoI have actually run into such problems and have solved them by scoping the macros with just {}, does this approach (do {} while(0)) have any advantages over scoping? Thanks..
Only the advantage that you can (and you have to) always put a semicolon after it, whereas you can't always put semicolon after {}. So the macro behaves more like normal function call.
Re: CEGUI+Custom memory allocator
Kulik wrote:I am currently walking through classes, marking which ones should be custom allocated and which ones should not.
Just making a note that most real games have very strict heap requirements. It would be preferable if all heap allocations could be customized, especially with a library like CEGUI that must be run entirely in an already tight rendering thread. Use of the system heap is bad, bad, bad.
Re: CEGUI+Custom memory allocator
Timo wrote:Kulik wrote:Thanks for the nitpicking TimoI have actually run into such problems and have solved them by scoping the macros with just {}, does this approach (do {} while(0)) have any advantages over scoping? Thanks..
Only the advantage that you can (and you have to) always put a semicolon after it, whereas you can't always put semicolon after {}. So the macro behaves more like normal function call.
You're right, scoping allows the semicolon whilst do {} while(false) requires it so the latter is definitely better.
JerryM wrote:Kulik wrote:I am currently walking through classes, marking which ones should be custom allocated and which ones should not.
Just making a note that most real games have very strict heap requirements. It would be preferable if all heap allocations could be customized, especially with a library like CEGUI that must be run entirely in an already tight rendering thread. Use of the system heap is bad, bad, bad.
So are you suggesting that everything in CEGUI should be custom allocated? The problem with this is quite simple, I found out (just by experiment) that for some classes (especially really small ones) custom allocation slows things down. It's not very noticeable but the difference is there. Ogre for example custom allocates everything except really small classes. I haven't yet researched this so the decision isn't final but I was going to skip CEGUI::colour, because when it's custom allocated it gets slower. I think this could be related to some compiler optimisations that are disabled when new and delete are overriden... I will look into it a bit more by the end of the week.
Re: CEGUI+Custom memory allocator
Yes. Perhaps not by default for all users, but it would be really great if it was there for more advanced users.Kulik wrote:So are you suggesting that everything in CEGUI should be custom allocated? The problem with this is quite simple, I found out (just by experiment) that for some classes (especially really small ones) custom allocation slows things down. It's not very noticeable but the difference is there. Ogre for example custom allocates everything except really small classes. I haven't yet researched this so the decision isn't final but I was going to skip CEGUI::colour, because when it's custom allocated it gets slower. I think this could be related to some compiler optimisations that are disabled when new and delete are overriden... I will look into it a bit more by the end of the week.
Re: CEGUI+Custom memory allocator
OK, I replaced the delete macros with Timo's code and finished up inheriting everything imaginable from AllocatedObject ![Wink ;-)](./images/smilies/icon_wink.gif)
The problem right now is that there are tons of allocator typedefs, I would like to merge some of them to make maintenance easier.
The only up to date allocator is the Ogre one right now.
I would definitely merge all *ModuleAllocator and all *FactoryAllocator classes. I want to allow as much flexibility as possible but I don't want to go overboard.
TrivialAllocator is used for classes that are trivial and unlikely to be heap allocated (Vector2, 3, colour, ColourRect, ...).
What else should possibly get merged? I imagine 95% of the devs are going to use one allocator for everything anyways so making it simpler for the 95% while making it flexible enough for the remaining 5% is my goal.
Since my server died, I have filled the request in mantis and uploaded the latest patch (it still is far from stable and clean code!) - http://cegui.org.uk/mantis/view.php?id=407
EDIT: I think I will go the template specialisation way in the end (same as Ogre3D). This will make it easy to set one default allocator and specialise the template for any exceptions.
![Wink ;-)](./images/smilies/icon_wink.gif)
The problem right now is that there are tons of allocator typedefs, I would like to merge some of them to make maintenance easier.
The only up to date allocator is the Ogre one right now.
Code: Select all
typedef ::Ogre::GeneralAllocPolicy DefaultAllocator;
typedef DefaultAllocator AnimationAllocator;
typedef DefaultAllocator AnimationInstanceAllocator;
typedef DefaultAllocator BiDiVisualMappingAllocator;
typedef DefaultAllocator DynamicModuleAllocator;
typedef DefaultAllocator EventAllocator;
typedef DefaultAllocator EventArgsAllocator;
typedef DefaultAllocator FactoryModuleAllocator;
typedef DefaultAllocator FontAllocator;
typedef DefaultAllocator FormattedRenderedStringAllocator;
typedef DefaultAllocator GeometryBufferAllocator;
typedef DefaultAllocator ImageAllocator;
typedef DefaultAllocator ImageCodecAllocator;
typedef DefaultAllocator ImagesetAllocator;
typedef DefaultAllocator InterpolatorAllocator;
typedef DefaultAllocator LoggerAllocator;
typedef DefaultAllocator PropertyAllocator;
typedef DefaultAllocator RawDataContainerAllocator;
typedef DefaultAllocator RegexMatcherAllocator;
typedef DefaultAllocator RenderedStringAllocator;
typedef DefaultAllocator RendererAllocator;
typedef DefaultAllocator RenderEffectAllocator;
typedef DefaultAllocator RenderEffectFactoryAllocator;
typedef DefaultAllocator RenderingSurfaceAllocator;
typedef DefaultAllocator RenderQueueAllocator;
typedef DefaultAllocator RenderTargetAllocator;
typedef DefaultAllocator ResourceProviderAllocator;
typedef DefaultAllocator SchemeAllocator;
typedef DefaultAllocator ScriptModuleAllocator;
typedef DefaultAllocator SingletonAllocator;
typedef DefaultAllocator StringAllocator;
typedef DefaultAllocator STLAllocator;
typedef DefaultAllocator SubscriberAllocator;
typedef DefaultAllocator TextureAllocator;
typedef DefaultAllocator TrivialAllocator;
typedef DefaultAllocator WindowAllocator;
typedef DefaultAllocator WindowFactoryAllocator;
typedef DefaultAllocator WindowRendererAllocator;
typedef DefaultAllocator WindowRendererModuleAllocator;
typedef DefaultAllocator XMLAttributesAllocator;
typedef DefaultAllocator XMLHandlerAllocator;
typedef DefaultAllocator XMLParserAllocator;
typedef DefaultAllocator XMLSerializerAllocator;
I would definitely merge all *ModuleAllocator and all *FactoryAllocator classes. I want to allow as much flexibility as possible but I don't want to go overboard.
TrivialAllocator is used for classes that are trivial and unlikely to be heap allocated (Vector2, 3, colour, ColourRect, ...).
What else should possibly get merged? I imagine 95% of the devs are going to use one allocator for everything anyways so making it simpler for the 95% while making it flexible enough for the remaining 5% is my goal.
Since my server died, I have filled the request in mantis and uploaded the latest patch (it still is far from stable and clean code!) - http://cegui.org.uk/mantis/view.php?id=407
EDIT: I think I will go the template specialisation way in the end (same as Ogre3D). This will make it easy to set one default allocator and specialise the template for any exceptions.
Return to “CEGUI Library Development Discussion”
Who is online
Users browsing this forum: No registered users and 6 guests