PDA

View Full Version : Resource Disposal problem



Xerelin
11-23-2011, 10:14 AM
Hi, I'm working on a project that will streamline dynamic pharmacy label printouts. The way my company designs them currently is in HP/GL2 and PCL. That's very archaic and restrictive.

I have built a program in C# that loads in the source code, parses it and displays it in an OpenGL environment to the screen to preview it before sending it to the printer.

Unfortunately, every time the user clicks over to the preview tab from another tab the mem usage goes up. I've been looking all over for a way to get rid of this problem, but I can't find a good way to remove the old resources instead of just piling up on top of the old.


public void glDrawCube()// To be in OpenGL style it I gave it a gl prefix
{
Texture = new OpenGLTexture2D(textureref);
GL.glTranslatef(-1.0f, -1.0f, fViewPort); // viewport = 0 0 0 and this is 6 deep
if (bRotateCheck == true)
{
GL.glRotatef(fRotate, 1.0f, 1.0f, 1.0f);
}
if (Form1.Stock == "Small")
{
Texture.Bind();
GL.glBegin(GL.GL_QUADS);// start drawing the cube
GL.glColor3fv(fColor); // Color with an array of floats
//Draw the front (only) face of the square

//top right
GL.glVertex3f(fPlusPosition - 0.05f, fPlusPosition + 0.7f, fPlusPosition);
GL.glTexCoord2f(0.0f, 1.0f);
//top left
GL.glVertex3f(fMinusPosition + 0.35f, fPlusPosition + 0.7f, fPlusPosition);
GL.glTexCoord2f(0.0f, 0.0f);
//bottom left
GL.glVertex3f(fMinusPosition + 0.35f, fMinusPosition - 0.4f, fPlusPosition);
GL.glTexCoord2f(1.0f, 0.0f);
//bottom right
GL.glVertex3f(fPlusPosition - 0.05f, fMinusPosition - 0.4f, fPlusPosition);
GL.glTexCoord2f(1.0f, 1.0f);
GL.glEnd();// end drawing the cube

if (bRotateCheck == true)
{
fRotate += 2.5f;
}
}
else
{
Texture.Bind();
GL.glBegin(GL.GL_QUADS);// start drawing the cube
GL.glColor3fv(fColor); // Color with an array of floats
//Draw the front (only) face of the square

//top right
GL.glVertex3f(fPlusPosition + 0.1f, fPlusPosition + 0.5f, fPlusPosition);
GL.glTexCoord2f(0.0f, 1.0f);
//top left
GL.glVertex3f(fMinusPosition + 0.3f, fPlusPosition + 0.5f, fPlusPosition);
GL.glTexCoord2f(0.0f, 0.0f);
//bottom left
GL.glVertex3f(fMinusPosition + 0.3f, fMinusPosition - 0.1f, fPlusPosition);
GL.glTexCoord2f(1.0f, 0.0f);
//bottom right
GL.glVertex3f(fPlusPosition + 0.1f, fMinusPosition - 0.1f, fPlusPosition);
GL.glTexCoord2f(1.0f, 1.0f);
GL.glEnd();// end drawing the square

if (bRotateCheck == true)
{
fRotate += 2.5f;
}
}
}

This is the method that creates a square and textures the base image onto it. I was wondering if there's a better way to do this, or if there's a way to clean up any old resources before displaying the new instance of it?

Thanks.

tksuoran
11-23-2011, 10:25 AM
You could surround Texture = new OpenGLTexture2D(textureref) with something like if(Texture != null){ ... }.

Also make sure your OpenGLTexture2D() does not hold unnecessary copies of the texture data.

Xerelin
11-23-2011, 10:40 AM
Thanks for the fast response.
So, I assume you mean something like adding an instance reference to the class like this:

private Bitmap m_textureref = null;
public Bitmap textureref
{
get
{
return m_textureref;
}
set
{
m_textureref = value;
}
}

I make the textureref = the texture loaded in my Cube method. Then, in glDrawCube I add the conditional:


if (textureref != null)
{
Texture = new OpenGLTexture2D(textureref);
}

Is that about right, or did I just completely miss what you were getting at?

Thanks again.

Xerelin
11-23-2011, 11:05 AM
Sorry about the double post, but a change in symptom has occured. I noticed first that the "mem usage" in Windows Task Manager would always increase when the user switched to the OpenGL preview tab.

Now I have observed that the CPU usage never really spikes and it never permanently increases, however, the PF Usage (Page File Usage) goes up every time the OpenGL preview tab is made active.

If anyone has any suggestions, I'm all ears.

thokra
11-23-2011, 02:00 PM
Since C# defaults to garbage collection, which is usally done in some interval, it may take time to deallocate used portions of memory. I only know this from Java, but is there an explicit way to have the runtime perform garbage collection? Does the memory usage decline over time? If explicit GC is possible, does it change anything?

As far as I know, C# lets you disable automatic memory management. In this case, do it the C++ way. Allocate and deallocate manually and see if it works. If it does, its the garbage collection.

The above problem is nothing OpenGL related per se. What I could think of is that the textures you generate aren't resident, meaning that your GL implementation is not storing texture data in video but in system memory.

To check for that, delete the texture object after rendering. If this works, it's the GL.

tksuoran
11-24-2011, 06:45 AM
No, that is not what I meant. That code would still do Texture = new OpenGLTexture2D(textureref); practically every time. What you need is create Texture only once.

Put debug printing or break point to texture constructor. Generally you should not be generating new textures every time draw.

Xerelin
11-25-2011, 08:25 AM
ok, So I recoded the method to only open the texture if something changes to warrant a new texture or if there isn't one on it yet.

Additionally, I took your advice on the garbage collection. Here's what I did:


private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
if (this.tabControl1.SelectedTab == tabPage2)
{
this.Design.Dispose();
GC.Collect();
}
if (this.tabControl1.SelectedTab == tabPage1)
{
this.Design = new Bones_IDE.GraphicsView();
this.Design.Parent = tabPage1;
this.Design.Dock = DockStyle.Fill; // Will fill whole Tab 1 page
this.Design.glDraw();
}
}

"Design" is my OpenGL environment class.
This completely removes the OpenGL environment from memory when not in use. Since I only need ~3-4 2D objects rendered in 3D space at a time, it's not hard to re-render.

This solution REALLY freed up a lot of memory usage. I went from ~94,000k and increasing to 54,000k when not using the environment and 76,000k when I was.

Thanks for the advice.