memory usage increasing

gugus

01-06-2008 15:57:04

I made some test,and i get some strange results.
If I do this:

pSysteme->pScene->createActor("te",new NxOgre::Sphere(1),NxOgre::Pose(0,0,0),mParams);
pSysteme->pScene->destroyActor("te");

It should leave all the memory free.
The program use 40Mo of RAM.

then i change these lignes into:
for(int i=0;i<20000;i++)
{

pSysteme->pScene->createActor("te",new NxOgre::Sphere(1),NxOgre::Pose(0,0,0),mParams);
pSysteme->pScene->destroyActor("te");
}


And now the program use 60 Mo...

betajaen

01-06-2008 16:31:56

It does clean up and things get deleted. What is the memory usage before adding that actor 20,000 times?

gugus

01-06-2008 16:38:15

the memory usage is approximativly 40 Mo before creating/deleting 20000 an actor.(It's not very accurate as I use ctrl+alt+del^^).
And after the programm does only root->startRendering().(note that i have these results during the rendering)

reptor

01-06-2008 17:51:38

If you are looking at the memory usage from Windows' Task Manager.

Is it possible that it is actually Windows on purpose keeping the memory allocated to the process even though the process released it? As an attempt to improve performance the next time the same process asks for more memory.

I don't know. But I've been wondering about this for some time.

luis

01-06-2008 19:22:52

Is it possible that it is actually Windows on purpose keeping the memory allocated to the process even though the process released it? As an attempt to improve performance the next time the same process asks for more memory.
Windows doing something like that ? Microsoft Windows ? attempting to increase performance ? hehe... no no, windows is not doing that.... :twisted:

There are memory pools to increase performance, but it is a developer's task.

@gugus, you could try using 'perfmon', just run it and press Ctrl+I and add you app (tunne up the graph scale).

The Demo_nxogre-0.1 I just posted:
http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=7345
is perfect to see that, press 1 and see if the memory stays the same.

Since there are many "garbage collectors" in Ogre and NxOgre, and some of NxOgre GC let you add pointers without forcing you have a unique ID it could end in a memory leak that wont be catched by Ogre's MemoryManager (or any other).

luis

01-06-2008 19:31:52

I did the test (Demo_nxogre-0.1) right after the app started:
49.132Mb
After pressing 5 times the key 1 (reloading heightmap and objects) the app has:
51.484Mb.

So, yes, there is a memory leak, although after shutting doing NxOgre/Ogre/Phyxs everything is leased, there is a memory leak during the app life.

I think the reason is the heightfield is never released.... I solved it in my game with a work-around. I can post it tomorrow and see if the memory stays the same.

betajaen

01-06-2008 19:41:31

But your using NxOgre without the new resource system; which keeps track of such things. Anything allocated through the resource system uses the Allocator class in NxOgre which dumps a log on shutdown. I don't get any leaks from that, and the Ogre leak reporter only reports some leaks I get in Cake.

gugus

01-06-2008 20:25:06

I am going to make more accurate test tommorow,but still i am nearly sure that it doesn't come frome my programm.

Ps:I never used debugger :oops: :oops: are they usefull to track memory leak?

reptor

01-06-2008 20:59:56

Is it possible that it is actually Windows on purpose keeping the memory allocated to the process even though the process released it? As an attempt to improve performance the next time the same process asks for more memory.
Windows doing something like that ? Microsoft Windows ? attempting to increase performance ? hehe... no no, windows is not doing that.... :twisted:

There are memory pools to increase performance, but it is a developer's task.


Actually, I remembered that Sinbad the Ogre3D programmer talked about this subject some time ago in a way which suggested that the Task Manager could show wrong value. I don't know if he was guessing, "playing it safe" or does he have real knowledge of it.

That talk by Sinbad was what got me thinking about it originally. I had never before questioned Task Manager :lol:

luis

03-06-2008 08:46:29

I dont trust in taskmanager neither.... that is why I suggested to use 'perfmon'.... at least it seems to be better. Any way for tests we are doing now both are enough accurate....

I made the change in the Demo_nxogre to release the heightfield and I had almost the same results. The increase in memory usage was just a bit slower.
I read something in Ageia's docs about releasing less memory than the real alocated memory to improve performance (perhaps they have a memory pool or something like that).
But if i allocate exactly the same amount of memory (loading/releasing the same heightfield, the same number of objects etc) I dont see any logical reason to have that 'leak' in the application. It should stay the same!

reptor

03-06-2008 19:39:35

Yeah it's not good, especially if the application is long-running like a server, then it can even be a very critical bug.

betajaen

03-06-2008 19:53:16

I wouldn't be to critical about PhysX especially when using the TaskManager as some sort of measurement device.

I've been working with PhysX and Plastic lately; and writing a new memory allocator system that is open enough to be worked with Havok and PhysX but to be professional and clean to work with. Just [b]creating the SDK with no Scenes uses 34KB[/b]; a majority of that is taken up by the remote debugger. How I know this? The allocator is very clean ;).

My point is, what ever PhysX uses - it cleans up.

gugus

03-06-2008 21:29:25

I had to change my hard drive so i have to re-install everything...
I will try to make further test with 'perfmon',with a code as simple as possible.

luis

04-06-2008 08:54:22

I will try to make further test with 'perfmon',with a code as simple as possible.
that would be good.
Taskmanager isn't perfect probably, may be it doesnt have too much accuracy etc, but we're talking about Mb...
I'll use perfmon with my test this afternoon and post my results.

Yeah it's not good, especially if the application is long-running like a server, then it can even be a very critical bug.

Yes, you're right, it is a critical bug. After loading 4 tracks in my game the memory allocated raised by 50Mb !

I want to explain even more what I think about this problem..... I use VLD and OgreMemoryManager and both can not detect any memory leak when the application ends and I beleive in those tools. So to me is very clear that: PhysX, NxOgre, Ogre and my App are doing a good job cleaning and releasing every thing before terminating the execution. The problem is what are they doing during the execution, that's why I talked about garbage collectors. And it is very hard to know...

luis

04-06-2008 20:59:46

permon results:
Private bytes for Demo_nxogre.exe process:
minimum: 49298304 (~49Mb)
maximum: 51210421 (~51Mb)
(check my previous post and you'll see the numbers are really close to taskmanager results).

The maximum peak was after pressing key 1 five times (reloads terrain and objects). If continue pressing the key, guess what? yes, the assigned memory for the process continues raising.

BTW: the work around to really-release :) the height field is:

//---------------------------------------------------------------------------
/*!
load/reload terrain (physics and graphics)
*/
void Globals::reloadAll()
{
// destroy all objects
_removeAllObjects();
// destroy previous terrain collision
// Note, due to a bug in NxOgre 1.0-XX (also in 0.9) it will leave a 'zombie' heightfield
// in Physx, you can (and should) manually remove it from Physx's scene
// I'll do it now with this work-around:
NxHeightFieldShape *hfs = 0;
NxHeightFieldShapeDesc hfd;
if( mTerrainCollision )
if( mTerrainCollision->getNxActor()->getNbShapes() > 0 )
{
NxShape*const *shapes = mTerrainCollision->getNxActor()->getShapes();
hfs = shapes[0]->isHeightField();
if( hfs )
hfs->saveToDesc( hfd );
}
mNxScene->destroyActor( Globals::TERRAIN_ACTOR_NAME );
mTerrainCollision = 0;
if( hfs )
mNxWorld->getPhysXDriver()->getSDK()->releaseHeightField( *hfd.heightField );
mTerrainCollision = 0;
// load/reload graphics
_loadOgreTerrain();
// load/reload physics
_loadNxOgreTerrain();
// finally create all objects again
createAllObjects();
}

gugus

05-06-2008 16:35:01

I did not manage to get perfMon working :oops: :oops: ,but I still get the same resluts with the task manager.

Here is my code:
#include "ExampleApplication.h"
#include <NxOgre.h>
#include <Ogre.h>


using namespace NxOgre;
using namespace Ogre;



class DemoFrameListener : public ExampleFrameListener
{
public:
DemoFrameListener(RenderWindow* win, Camera* cam,Scene* scene)
: ExampleFrameListener(win, cam, false, false)
{
mScene = scene;
}

bool frameStarted(const FrameEvent &evt)
{
mKeyboard->capture();

return ExampleFrameListener::frameStarted(evt);
}


protected:
Scene* mScene;
};

class DemoApplication : public ExampleApplication
{
protected:
public:
DemoApplication()
{

}

~DemoApplication()
{
delete mWorld;
}

void CreateWorld()
{
PhysXParams mParams;
mParams.setToDefault();
mParams.mTimeController = PhysXParams::TC_OGRE;
mParams.mUseLog = true;

mWorld = new World(mParams);
}

void CreateNxScene()
{
SceneParams mParams;
mParams.setToDefault();
mParams.mGravity = NxVec3(0,-9.8,0);
mParams.mFloor = true;

mScene = mWorld->createScene("test Scene",mParams);
}

protected:
void createScene(void)
{
}
void createFrameListener(void)
{
CreateWorld();
CreateNxScene();
mFrameListener = new DemoFrameListener(mWindow, mCamera,mScene);
mRoot->addFrameListener(mFrameListener);

NxOgre::ActorParams mParams;
for(int i=0;i<20000;i++)
{
NxOgre::Cube* mCube = new NxOgre::Cube(1);
mScene->createActor("te",mCube,Ogre::Vector3(0,0,0),mParams);
mScene->destroyActor("te");
//delete mCube;
}

}

protected:
World* mWorld;
Scene* mScene;
};

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
DemoApplication app;

try {
app.go();
} catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occurred: %s\n",
e.what());
#endif
}

return 0;
}