Page 1 of 1

TChart 3.0 Performance

Posted: Fri Apr 04, 2008 1:42 pm
by 13048566
I've recently updated my RealTime financial updating graphs from TChart .NET 2.0 to TChart 3.0 and am having some performance issues. I've already read the Document on RealTime Charting, and understand all those issues.

Something I noticed that has changed in TChart 3.0 is that it doesn't seem to update automatically anymore. It seems that in the last version, when I added a point to a series or added a series to the graph, it would automatically redraw. Now I have to call Refresh on the TChart, after adding each point/series. I have TChart.AutoRepaint set to true. Is there a reason that this changed?

I'm also trying to get the TChart to perform better on all of these refreshes. It currently spikes the processor at times. What is the best way to refresh the TChart after a change? The majority of the time only the last point is updating or being added to. Would invalidating just the region of that last point help performance or is it going to cause the whole TChart to redraw anyways....

Any advice you can give me would be great!

Thanks.

Posted: Fri Apr 04, 2008 2:24 pm
by narcis
Hi TMac,

Could you please send us a simple example project we can run "as-is" to reproduce the problem here? You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at our upload page.

Thanks in advance.

Posted: Fri Apr 04, 2008 3:16 pm
by 13048566
I posted the test project to the Upload page.

You'll see that it automatically refresh for a while, then all of a sudden it will stop refreshing.

Posted: Fri Apr 04, 2008 3:51 pm
by narcis
Hi TMac,

Thanks for the example project. I have had it running for a while but it is still refreshing. At this moment MaxYValue is about 2500. Should it have stopped refreshing now? Should I follow any specific step to reproduce the issue?

Thanks in advance.

Posted: Fri Apr 04, 2008 6:19 pm
by 13048566
I did some more testing, and it seems to consistently do it on my development machine. Sometimes it doesn't happen by the 100th pass, but if I restart it, it usually does.

I'm using a 64-bit machine, I ran it on a 32-bit machine in our office, and I couldn't reproduce it. Is it possible that it is a 64-bit issue? Or is adding the points asyncronously like this a bad idea? I tried throwing a Synclock around the adding of the point, but it didn't help.

Posted: Mon Apr 07, 2008 2:01 pm
by narcis
Hi TMac,

Thanks for the information. We could reproduce the issue here in a 64 bit machine and could solve it setting UseBuffer=False at chart's initialization code, for example:

Code: Select all

TChart.Graphics3D.UseBuffer=False
UseBuffer is a new property in v3 that enables/disables manual double-buffering. For more information on this property please read this thread.

Posted: Tue Apr 08, 2008 2:19 pm
by 13048566
I made this change to UserBuffer = false, but now the whole graph flashes everytime the graph redraws, which is because the double-buffering is off I guess.

So, that fix isn't really going to work for me. Is there any way to make it work like it used to, because doing the explicit refresh on every update is killing performance. We're considering flipping back to TChart 2.0, is that the best solution for this?

Posted: Wed Apr 09, 2008 8:46 am
by Chris
Hello,
TMac wrote:I made this change to UserBuffer = false, but now the whole graph flashes everytime the graph redraws, which is because the double-buffering is off I guess.


That's right.
TMac wrote: So, that fix isn't really going to work for me. Is there any way to make it work like it used to, because doing the explicit refresh on every update is killing performance. We're considering flipping back to TChart 2.0, is that the best solution for this?
Steema's implementation of "manual" double buffering has greatly increased performance in just about all areas in which TeeChart clients use the chart. Using this "manual" double buffering even works fine when adding points to the chart asynchrously under the x86 version of .NET 3.5. However, we have been able to find a solution to the problem under x64 which I post below:

Code: Select all

  public partial class Form3 : Form
  {
    public Form3()
    {
      InitializeComponent();
      InitializeChart();
    }

    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;
      tChart1.Series.Add(line1 = new Line());
      TimerCallback timerDelegate = new TimerCallback(AddToSeriesAsyncTimer);
      timer = new System.Threading.Timer(timerDelegate);
    }

    private delegate void AddAsyncDelegate();
    private System.Threading.Timer timer;

    private void AddToSeries() 
    {
      AddAsyncDelegate caller = new AddAsyncDelegate(AddToSeriesAsync);
      IAsyncResult result = tChart1.BeginInvoke(caller);
      tChart1.EndInvoke(result);
    }


    private Steema.TeeChart.Styles.Line line1;

    private void AddToSeriesAsyncTimer(Object stateInfo)
    {
      if (line1.MaxYValue() < 1000)
      {
        tChart1.Chart.Graphics3D.BackBuffer = null;
        line1.Add(line1.MaxXValue() + 1, line1.MaxYValue() + 1);
      }
    }

    private void AddToSeriesAsync()
    {
      timer.Change(0, 500);
    }

    private void button1_Click(object sender, EventArgs e)
    {
      AddToSeries();
    }
This simply involves setting the backbuffer to null to force the chart to re-create it, which we don't think will adversly affect performance (it certainly doesn't in the above example).

Posted: Wed Apr 09, 2008 2:53 pm
by 13048566
That fix seems to work in the example, but if you try making the timer faster, it breaks. I get the same breaking effect in my app.

Clearing the Buffer asynchronously like that seems to be pretty dangerous, it crashes when the TChart is also using it to paint.[/code]

Posted: Wed Apr 09, 2008 3:59 pm
by 13048566
I came up with a fix for the crashing I was experiencing in my last post.

I overrode the TChart and put a lock in the OnPaint method, and the same lock around clearing the backbuffer. That seems to have fixed the problem. I can now run the test project and my app at full speed, and they don't crash.

Code: Select all

Public Class x
    Inherits Steema.TeeChart.TChart
    Private m_Lock As New Threading.ReaderWriterLock()

    Public ReadOnly Property LockObject() As Threading.ReaderWriterLock
        Get
            Return m_Lock
        End Get
    End Property

    Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
        m_Lock.AcquireWriterLock(100000000)
        MyBase.OnPaint(pe)
        m_Lock.ReleaseWriterLock()
    End Sub
End Class

Code: Select all

    Private Sub AddToSeriesAsync()
        While field.MaxYValue < 100000

            TChart.LockObject.AcquireWriterLock(1000000)
            TChart.Chart.Graphics3D.BackBuffer = Nothing
            TChart.LockObject.ReleaseWriterLock()

            field.Add(field.MaxXValue + 1, field.MaxYValue, field.MaxYValue - 1, field.MaxYValue + 2, field.MaxYValue + 1)
        End While
    End Sub
This seems to work really well so far.

Posted: Thu Apr 10, 2008 7:11 am
by Chris
TMac,
TMac wrote:This seems to work really well so far.
I'm pleased to hear it and thanks for the feedback.

IMO, asynchronous painting is a pretty hairy beast in general. I think the proof of this statement is that not even the .NET Framework can get it to work identically on two different platforms (x64 and x86).