Memory Leak when removing Objects from World?

Started by sticksen, December 30, 2011, 11:12:12 PM

Previous topic - Next topic

sticksen

Hi,

I´ve got this following mini project: http://db.tt/aslRLtOp
In this simplistic app, every frame all objects are cleared from the world and then one new object is added. If I run it, the consumed memory continously begins to grow. Why is that?

I came across this problem because in a bigger project, I have to add around 500 Object3Ds with 400 Vertices each continously again and again, i.e. remove them from the world, add them again, remove them etc.
With every step my app consumed 50MB more of Heapsize!

Anybody with a clue?

Cheers, Marc

EgonOlsen

That test case is flawed, because it never calls FrameBuffer.display(). By not doing this, you are creating a new visibility every frame (see log output), which eats up your memory after some time. When adding this call, i can't find any memory problem with this test case. I've modified your test case to print out memory usage every 10 seconds using the MemoryHelper class and it never exceeds 2812kb...


package bla.blubb;

import java.util.Enumeration;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.util.Log;

public class TestActivity extends Activity {
    private World world;
   
    private long time=0;

/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GLSurfaceView gLSurfaceView = new GLSurfaceView(getApplicationContext());
        setContentView(gLSurfaceView);
        world = new World();
        gLSurfaceView.setRenderer(new Renderer() {

private FrameBuffer fb;
private Object3D obj;

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Camera cam = world.getCamera();
cam.setPosition(0, 0, -10);
cam.setOrientation(new SimpleVector(0,0,0), new SimpleVector(0,1,0));
world.setAmbientLight(255, 255, 255);
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
fb = new FrameBuffer(gl, width, height);
}

@Override
public void onDrawFrame(GL10 gl) {
world.removeAllObjects();
obj = Primitives.getSphere(5);
obj.setAdditionalColor(RGBColor.RED);
obj.setCulling(Object3D.CULLING_DISABLED);
world.addObject(obj);
world.buildAllObjects();
fb.clear(RGBColor.BLACK);
world.renderScene(fb);
world.draw(fb);
Enumeration<Object3D> objs = world.getObjects();
while (objs.hasMoreElements()){
Object3D elem = objs.nextElement();
Log.v("Test", "obj "+elem.getName()+","+elem.getID());
}
fb.display();

if (System.currentTimeMillis()-time>=10000) {
MemoryHelper.compact();
time=System.currentTimeMillis();
}
}
});
       
    }
}

sticksen

Wow! That was a quick and easy fix, thank you! I don´t know at which developing step I left fb.display() out, and I´m still wondering why the program at all worked without this line, but now it´s good again!

Cheers,
Marc

EgonOlsen

It works because display() doesn't do much in jPCT-AE (compared to desktop jPCT). It renders into a texture, if that feature is used, and it keeps track of the visibility lists. You can render multiple worlds into one frame buffer in one frame, but the engine has to create multiple visibility lists for this. So if you omit display(), it thinks that you still want to render everything in one frame because it doesn't recognize that the frame has changed and creates visibility list after visibility list...