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:
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).