Page 1 of 1

Direct 2D memory leak?

Posted: Sat Jul 13, 2013 4:53 pm
by 15666280
Hi everyone,
I am having a problem with a consistently re-occuring out of memory error in my application using a simple 2D Tchart with Direct2D. While I am not entirely sure if I am using Direct2D correctly, I put together a simple example that has the same problem: it uses increasing amounts of memory and eventually causes an out of memory error. The only thing on the Form is a TChart object.

I am using Visual Studio 2012 with TChart 2013 for .net ( 4.1.2013.05280) and the latest version of SimDX.

Thanks!

Scott

public partial class Form1 : Form
{
Steema.TeeChart.Styles.FastLine dsa;
Steema.TeeChart.Styles.FastLine dsb;
int xcounter;
public Form1()
{
InitializeComponent();
dsa = new Steema.TeeChart.Styles.FastLine();
dsb = new Steema.TeeChart.Styles.FastLine();
Graphics3DDirect2D D2D = new Graphics3DDirect2D(tChart1.Chart);
D2D.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
D2D.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
tChart1.Graphics3D = D2D;
tChart1.Graphics3D.BufferStyle = BufferStyle.None;


tChart1.Aspect.View3D = false;
tChart1.Legend.Visible = false;
tChart1.Header.Visible = false;
tChart1.Footer.Visible = false;
tChart1.Chart.Axes.Bottom.Title.Text = "Sample";
tChart1.Chart.Axes.Left.Title.Text = "Signal";

tChart1.Chart.Axes.Left.Automatic = false;
tChart1.Chart.Axes.Left.Minimum = 0;
tChart1.Chart.Axes.Left.Maximum = 1000;

tChart1.Chart.Axes.Bottom.Automatic = true;
tChart1.Chart.Axes.Bottom.Increment = 50;

tChart1.Chart.Legend.Alignment = LegendAlignments.Top;
tChart1.Legend.DrawBehind = false;
tChart1.Legend.ResizeChart = false;
tChart1.Legend.Visible = true;

tChart1.AutoRepaint = true;
tChart1.Chart.Series.Add(dsa);
tChart1.Chart.Series.Add(dsb);
xcounter = 1;
timer1.Start();
}

private void timer1_Tick(object sender, EventArgs e)
{
if (dsa.Count > 300)
{
dsa.Delete(0);
dsb.Delete(0);
}
dsa.Add(xcounter, 100);
dsb.Add(xcounter, 300);
tChart1.Refresh();
xcounter++;
}

Re: Direct 2D memory leak?

Posted: Mon Jul 15, 2013 11:26 am
by 10050769
Hello spletcher1,

Ok. I have modified a little your code and seems the memory leak doesn't appear using it with latest version of TeeChartFor.Net (Build 4.1.2013.05280):

Code: Select all

   Steema.TeeChart.Styles.FastLine dsa;
        Steema.TeeChart.Styles.FastLine dsb;
        int xcounter;
        Timer timer1; 
        private void InitializeChart()
        {
            //Create series and components
            dsa = new Steema.TeeChart.Styles.FastLine(tChart1.Chart);
            dsb = new Steema.TeeChart.Styles.FastLine(tChart1.Chart);
            timer1 = new Timer();
            Steema.TeeChart.Drawing.Direct2D.Graphics3DDirect2D D2D = new Steema.TeeChart.Drawing.Direct2D.Graphics3DDirect2D(tChart1.Chart);
            //InitializeChart
            D2D.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            D2D.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            tChart1.Graphics3D = D2D;
            tChart1.Graphics3D.BufferStyle = BufferStyle.None;
            tChart1.Aspect.View3D = false;
            tChart1.Legend.Visible = false;
            tChart1.Header.Visible = false;
            tChart1.Footer.Visible = false;
            //InitializeAxes
            tChart1.Chart.Axes.Bottom.Title.Text = "Sample";
            tChart1.Chart.Axes.Left.Title.Text = "Signal";
            tChart1.Chart.Axes.Left.Automatic = false;
            tChart1.Chart.Axes.Left.Minimum = 0;
            tChart1.Chart.Axes.Left.Maximum = 1000;
            tChart1.Chart.Axes.Bottom.Automatic = true;
            tChart1.Chart.Axes.Bottom.Increment = 50;
            tChart1.Axes.Left.AxisPen.UseStyling = false;
            tChart1.Axes.Bottom.AxisPen.UseStyling = false;
            tChart1.Axes.Left.Grid.UseStyling = false;
            tChart1.Axes.Bottom.Grid.UseStyling = false;
            //FastLines
            dsa.LinePen.UseStyling = false;
            dsb.LinePen.UseStyling = false;
            tChart1.Panel.Pen.UseStyling = false; 
            xcounter = 1;
            timer1.Start();
            timer1.Tick +=new EventHandler(timer1_Tick);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            tChart1.AutoRepaint = false;
          
            if (dsa.Count >300)
            {
                dsa.Delete(0);
                dsb.Delete(0);
            }
            dsa.Add(xcounter, 100);
            dsb.Add(xcounter, 300);
            xcounter++;
            tChart1.AutoRepaint = true;
            tChart1.Invalidate();
        }
Could you please confirm us if the memory leak appears for you using my code?

I hope will helps.

Thanks,

Re: Direct 2D memory leak?

Posted: Mon Jul 15, 2013 2:05 pm
by 15666280
Hi Sandra,
Thank you for your quick reply. Unfortunately, I still seem to be having the problem. For the code pasted below, I get the following levels of memory usage (KB) after short periods of running your code

40,000 after 5s
50,000 after 10s
64,000 - 25s
80,000 - 30s
120,000 - 60s
500,000 - 300s
etc.

While I didn't let it run to failure (my development machine has 64GB of RAM so I expect it would take awhile), I am pretty sure it would eventually. I am implementing on a small laptop, which crashes after about 15min in the original application, which has larger dataseries. Nevertheless, for this example, if I disable the Direct2D code by commenting lines(1)-(4), the usage rapidly stabilizes around 30,000KB, and remains unchanged for at least 5min. I don't see how more memory is used after 300 items are added to each dataseries, which happens after only a few seconds.

I have confirmed that I am using the same TeeChart version as you and my code used for this test is posted below.

Code: Select all

using System;
using System;
using System.Windows.Forms;
using Steema.TeeChart.Drawing;

namespace MemLeakTest
{
    public partial class Form1 : Form
    {
        Steema.TeeChart.Styles.FastLine dsa;
        Steema.TeeChart.Styles.FastLine dsb;
        int xcounter;
        Timer timer1;
        public Form1()
        {
            InitializeComponent();
            timer1 = new Timer();
            timer1.Interval = 5;
            InitializeChart();
            xcounter = 1;
            timer1.Start();
            timer1.Tick +=new EventHandler(timer1_Tick);
        }

        private void InitializeChart()
        {
            dsa = new Steema.TeeChart.Styles.FastLine(tChart1.Chart);
            dsb = new Steema.TeeChart.Styles.FastLine(tChart1.Chart);
            Steema.TeeChart.Drawing.Direct2D.Graphics3DDirect2D D2D = new Steema.TeeChart.Drawing.Direct2D.Graphics3DDirect2D(tChart1.Chart); //(1)
            //InitializeChart
            D2D.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; //(2)
            D2D.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //(3)
            tChart1.Graphics3D = D2D; //(4)
            tChart1.Graphics3D.BufferStyle = BufferStyle.None;
            tChart1.Aspect.View3D = false;
            tChart1.Legend.Visible = false;
            tChart1.Header.Visible = false;
            tChart1.Footer.Visible = false;

            //InitializeAxes
            tChart1.Chart.Axes.Bottom.Title.Text = "Sample";
            tChart1.Chart.Axes.Left.Title.Text = "Signal";
            tChart1.Chart.Axes.Left.Automatic = false;
            tChart1.Chart.Axes.Left.Minimum = 0;
            tChart1.Chart.Axes.Left.Maximum = 1000;
            tChart1.Chart.Axes.Bottom.Automatic = true;
            tChart1.Chart.Axes.Bottom.Increment = 50;
            tChart1.Axes.Left.AxisPen.UseStyling = false;
            tChart1.Axes.Bottom.AxisPen.UseStyling = false;
            tChart1.Axes.Left.Grid.UseStyling = false;
            tChart1.Axes.Bottom.Grid.UseStyling = false;
            //FastLines
            dsa.LinePen.UseStyling = false;
            dsb.LinePen.UseStyling = false;
            tChart1.Panel.Pen.UseStyling = false;
        }         
        private void timer1_Tick(object sender, EventArgs e)
        {
             tChart1.AutoRepaint = false;
            if (dsa.Count > 300)
            {
                dsa.Delete(0);
                dsb.Delete(0);
            }
            dsa.Add(xcounter, 100);
            dsb.Add(xcounter, 300);
            xcounter++;
            tChart1.AutoRepaint = true;
            tChart1.Invalidate();
        }

    }
}

Re: Direct 2D memory leak?

Posted: Wed Jul 17, 2013 11:00 am
by 10050769
Hello spletcher1,

Thank you for your information. After doing many test We have considered add your request in bug list report with number [TD29016647]. We will try to fix it to upcoming version of TeeChartDirec2D.

Thanks,

Re: Direct 2D memory leak?

Posted: Fri Jul 19, 2013 2:55 am
by 15666280
Hi Sandra,
Thank you for your response, but I don't quite understand your post. Does this imply that you have confirmed the bug and that, at present, the Direct2D routines will not be usable for my current application (or any application that deletes series data)?

Thanks,
Scott

Re: Direct 2D memory leak?

Posted: Fri Jul 19, 2013 1:15 pm
by narcis
Hi Scott,

We are currently investigating the issue. The problem doesn't occur with the Direct2D demo shipped with TeeChart installation. Can you reproduce it with the demo?

Thanks in advance.

Re: Direct 2D memory leak?

Posted: Fri Jul 19, 2013 10:27 pm
by 15666280
Okay. I agreed, the demo code as shipped does not exhibit a leak. However, after much painful elimination, I believe I was able to isolate the key lines of code:

tChart1.Panel.Gradient.Visible = false;
tChart1.Walls.Visible = false;
tChart1.Axes.Left.Grid.UseStyling = false;
tChart1.Axes.Bottom.Grid.UseStyling = false;

I believe that each of these, when set to true, seems to contribute to the memory leak (although to different magnitudes). Two bits of evidence support this. First, if I make sure to include all of these assignments in my original problem code (posted), the memory leak is gone. Second, if I comment out these statements in the demo code, the leak appears.

Again, i should note that this only happens when i use Graphics3DDirect2D. If I just do standard plotting, there is no problem.

Would you verify that you can reproduce this?

Scott

Re: Direct 2D memory leak?

Posted: Mon Jul 22, 2013 8:52 am
by narcis
Hi Scott,

Thanks for your feedback. We could reproduce the problem here and will try to fix it.

Re: Direct 2D memory leak?

Posted: Mon Jul 22, 2013 11:36 am
by narcis
Hi Scott,

As an update, we have fixed the issue for the next maintenance release due out very soon. The problem was with a SlimDX.Direct2D.Brush object not disposing its objects. Commented out code below didn't work, it was not disposing GradientStops. It might be a SlimDX defect. Anyway the fix below has just been implemented for the upcoming release.

Code: Select all

          //using(SlimDX.Direct2D.Brush b = GradientDrawingBrush(r)) gd.FillRectangle(b, r);
          SlimDX.Direct2D.Brush b = GradientDrawingBrush(r);
          try
          {
            gd.FillRectangle(b, r);
          }
          finally
          {
            if (b is LinearGradientBrush)
            {
              ((LinearGradientBrush)b).GradientStops.Dispose();
            }
            else
            {
              ((RadialGradientBrush)b).GradientStops.Dispose();
            }
            b.Dispose();
          }