Memory leak when i tried to switch views.

Started by kiffa, August 06, 2012, 05:19:26 AM

Previous topic - Next topic

kiffa

My app has 2 views, the one is SurfaceView, the other is GLSurfaceView. I need switch between them frequently, so i want to just load the models once and keep them in the memory in order to speed up the switching process.

The process:
entry SurfaceView -> switch to GLSurfaceView -> load models -> init world and others -> render and display world -> switch to SurfaceView -> switch to GLSurfaceView -> just use pre-loading models without reloading -> init world and others -> render and display world -> .....

But there seems a memory-leak in my test-app, my codes(some pseudo code):

//onSurfaceCreated

if(modelsPreloded)
  use preloadedModels and textures;
else
  loadModels() and initTextures();

initWorldAndOthers();
addAllModelsToWorld();
buildAllObjctes();

// onSurfaceChanged
  mFrameBuffer = new FrameBuffer(width, height);

// onDrawFrame
animate();
mWorld.renderScene(mFrameBuffer);
mWorld.draw(mFrameBuffer);
mFrameBuffer.display();

// onTouchEvent
if(touch down)
  mActivity.setContentView(new MyGLSurfaceView(mActivity));


With per touching down, the memory usage will increase about 500K. But what i expect is that there should be non memory usage increasing when switching from an old GLSurfaceView to the new one.

And if i change code to de-active "mWorld.renderScene(mFrameBuffer)" and "mWorld.draw(mFrameBuffer)", there will no memory usage increase when i touch down:

// onDrawFrame
animate();
//mWorld.renderScene(mFrameBuffer);
//mWorld.draw(mFrameBuffer);
mFrameBuffer.display();


Should i do some clear work before switching views? I tried mFrameBuffer.freeMemory() and mFrameBuffer.dispose(), seems useless.

EgonOlsen

dispose() definitely isn't useless. Even if you don't see any effect in this situation, it's mandatory to call it before the FrameBuffer goes out of scope. The same is true for world.dispose() in case you are creating a new one. Do these 500kb add up each time you do the switch or does it happen only once?

kiffa

#2
Quote from: EgonOlsen on August 06, 2012, 07:45:21 AM
dispose() definitely isn't useless. Even if you don't see any effect in this situation, it's mandatory to call it before the FrameBuffer goes out of scope. The same is true for world.dispose() in case you are creating a new one.
So, you do this in finalize() and i needn't  to call FrameBuffer.dispose() or world.dispose() manually if i ensure they could be recycled correctly by GC. Is that right?


Quote from: EgonOlsen on August 06, 2012, 07:45:21 AM
Do these 500kb add up each time you do the switch or does it happen only once?
Each time.


EgonOlsen

Quote from: kiffa on August 06, 2012, 10:56:20 AM
So, you do this in finalize() and i needn't  to call FrameBuffer.dispose() or world.dispose() manually if i ensure they could be recycled correctly by GC. Is that right?
Yes, but that will take some time to happen. If you are low on memory, it's better to call it explicitly.

Quote from: kiffa on August 06, 2012, 10:56:20 AM
Each time.
No idea then. You could try to debug tools that come with the plugin to track it down (http://www.jpct.net/wiki/index.php/Profiling_Android_Applications). It might be something strange that you are doing or a problem of jPCT-AE, but i'm not aware of any of that kind ATM. If nothing else helps, you could create a simple test case.

kiffa

#4
With per switch, there will add an extra GLSurfaceView object which have a jpct.VisList objcet of 500K memory usage. I will create a simple test case to check again.

EgonOlsen

I don't see how this can happen unless you don't dispose the FrameBuffer and/or the World(s) or are keeping some references to them.