ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  SurfaceChart rotation - memory leak
Posted by Bj?rn Tings on Jan-13-2011 23:12
Hi,

My name is Bj?rn Tings and I am working for WZL of RWTH Aachen. We use ChartDirector for .Net to plot surfaces of milled work pieces.

Unfortunately, ChartDirector does not provide methods for rotating and scaling charts using mouse or keyboard, so I implemented my own methods using Managed C++. All these methods call an update function to let the surface chart being redrawn. Especially by using the mouse for rotating the chart, this function is called quite often.

The function is shown below:

void Form_Graph_Normal_3D::update(bool plotSurface)
{
delete this->chart;
this->chart = nullptr;
// the perspective level
double perspective = 0;
// Create a SurfaceChart object with white
// (ffffff) background and grey (888888) border.
this->chart = gcnew SurfaceChart(this->chartSizeW,
this->chartSizeH, 0xffffff, 0x888888);

// Set the perspective level
this->chart->setPerspective(perspective);
this->chart->addTitle(this->titleBez);

// Set the center of the plot region and set width x depth
// x height
this->chart->setPlotRegion((int)(this->chartSizeW*0.5),
(int)(this->chartSizeH*0.5),
(int)(this->chartSizeW*0.5*2*zoomFaktor),
(int)(this->chartSizeH*0.5*zoomFaktor),
(int)(this->chartSizeH*0.5*0.5*zoomFaktor));

// Set the plot region wall thickness to 5 pixels
this->chart->setWallThickness(5);

// Set the elevation and rotation angles
this->chart->setViewAngle(this->viewAngleX,
this->viewAngleY, this->viewAngleZ);

//do not plot the graph during rotation
if(plotSurface)
{
// Set the data to use to plot the chart
this->chart->setData(this->x_array, this->y_array, this->z_array);
}

//set Data Grid on Surface
this->chart->setSurfaceDataGrid(0);

// Spline interpolate data for a smooth surface
this->chart->setInterpolation(1, 1);

// Use smooth gradient coloring.
this->chart->colorAxis()->setColorGradient();

// Set the x, y and z axis titles
this->chart->xAxis()->setTitle(this->xachseBez);
this->chart->yAxis()->setTitle(this->yachseBez);
this->chart->zAxis()->setTitle(this->zachseBez);

// Output the chart
try
{
delete graph3D->Image;
this->graph3D->Image = nullptr;
this->graph3D->Image = this->chart->makeImage();
}
catch (OutOfMemoryException^)
{
// try again
GC::Collect(2);
this->graph3D->Image = this->chart->makeImage();
}
}

During runtime I noticed that for every call of this function the used memory increases until the garbage collection starts or an OutOfMemoryException is thrown. Using GC::Collect() leads to hesitant rotations.
I made a few tests and found out that makeImage() may be responsible for this behaviour.

I had a deeper look into its source code.

public virtual Image makeImage()
{
    this.c();
    return this.e.outImage();
}
=>
public virtual Bitmap outImage()
{
    this.b();
    int capacity = (((((this.a9 * 3) + 3) / 4) * 4) * this.ba) + 0x36;
    MemoryStream stream = new MemoryStream(capacity);
    new aa(stream).a(this.bb, this.a9);
    return new Bitmap(stream);
}

Is there a possibility to pass an existing Bitmap- and MemoryStream-object, which will be reused, instead of reallocated ones? I don?t want the garbage collector to adjust its frequency of collections, because each collection slows down running speed. According to this fact, the best solution should be a solution without any garbage collection during rotations and reusing every object.

Kindest regards
Bj?rn Tings

  Re: SurfaceChart rotation - memory leak
Posted by Peter Kwan on Jan-14-2011 00:40
Hi Bj?rn,

In .NET, we must accept there is always some garbage collection. Even the .NET framework internally relies on garbage collection to clear up memory.

If you want to use your own memory stream, you can use something like:

DrawArea^ d = c->makeChart3();
d->setPaletteMode(Chart::NoPalette);
d->outBMP(myMemoryStream);
Image ^myImage = new Bitmap(myMemoryStream);

Note that there is a Dispose method in many .NET objects (including the Bitmap object). The .NET documentation says this method can be used to "free up resources", but it does not mention exactly what resources are freed up. You may try to see if calling this method can make any difference.

Hope this can help.

Regards
Peter Kwan