Speed up Live Plotting?

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Speed up Live Plotting?

Post by moelski » Wed Nov 11, 2009 7:28 am

Hello !

We have a problem with CPU consumption if we plot in a chart for a long time. Actually my data is generated by a timer which adds always one new point to each FastLineSeries. The timer interval can be configured : 10-1Sec, 0.5Sek, 0.25Sek, 0.2Sek, 0.1Sek.

If I start the application all works fine. We use some techniques to reduce the CPU usage (see code and explanation below). After starting the CPU usage is very low. Not more then 1% on a 450MHz system.

This is the code for adding data:

Code: Select all

procedure TChild_Grafik.PlotTimerTimer(Sender: TObject);
var I, j      : Integer;
    MilliSec  : Double;
    PlotDiff  : Integer;
    Plot      : Boolean;
begin
  MilliSec := MilliSecondsBetween(Now, StartZeit);

  MDIChart.AutoRepaint := PlotInterval.ItemIndex = 11;

  if ChartFloating.Checked then begin
    MDIChart.BottomAxis.Maximum := (MilliSec / 1000);
    MDIChart.BottomAxis.Minimum := (MilliSec / 1000) - FloatingTime.Value;
  end;

  MDIChart[0].AddXY((MilliSec / 1000), MDIChart[0].Count + 1);
  for I := 1 to MDIChart.SeriesCount - 1  do begin
    MDIChart[I].AddXY((MilliSec / 1000), (Sin(MDIChart[I].MaxXValue / (10 * (I + 1))) +
                                                 Cos(MDIChart[I].MaxXValue / (30 * (I + 1)))
                                                 * ((I + 1) * 3) ))
  end;

  if PlotInterval.ItemIndex <> 11 then begin
    PlotDiff := MilliSecondsBetween(Now, LastPlot);
    case PlotInterval.ItemIndex of
//      Plot every Hour
       0 : Plot := PlotDiff >= 60000 * 60;
//      Plot every 20 Minutes
       1 : Plot := PlotDiff >= 60000 * 20;
//      Plot every 10 Minutes
       2 : Plot := PlotDiff >= 60000 * 10;
//      Plot every 5 Minutes
       3 : Plot := PlotDiff >= 60000 * 5;
//      Plot every 2 Minutes
       4 : Plot := PlotDiff >= 60000 * 2;
//      Plot every Minute
       5 : Plot := PlotDiff >= 60000;
//      Plot every 20 seconds
       6 : Plot := PlotDiff >= 20000;
//      Plot every 10 seconds
       7 : Plot := PlotDiff >= 10000;
//      Plot every 5 seconds
       8 : Plot := PlotDiff >= 5000;
//      Plot every 2 seconds
       9 : Plot := PlotDiff >= 2000;
//      Plot every second
      10 : Plot := PlotDiff >= 1000;
//      Plot always
      11 : Plot := True;
//      Plot max. 2x / Sec
      12 : Plot := PlotDiff >= 500;
//      Plot max. 4x / Sec
      13 : Plot := PlotDiff >= 250;
//      Plot max. 10x / Sec
      14 : Plot := PlotDiff >= 100;
    end;

    if Plot then begin
      LastPlot := Now;
      MDIChart.AutoRepaint := True;
      MDIChart.Refresh;
    end;
  end;
end;
Ok let me explain the code a little bit ...
PlotInterval is a ComboBox with some entries. You can select how often the chart will be repaint.
And itemindex 11 means -> plot always if points are added.

if ChartFloating.Checked then begin
MDIChart.BottomAxis.Maximum := (MilliSec / 1000);
MDIChart.BottomAxis.Minimum := (MilliSec / 1000) - FloatingTime.Value;
end;

This code is used to float the x Axis. So the chart would only show the last X entries.

The naxt part in the code is for adding the new points to the series.

The next big part is used to reduce the count of repaints of the chart. A normal FastLineSeries would be repaint if a point is added. To avoid this we use this code to repaint only all x seconds. This reduces CPU usage extremly.

Ok so far the explanation to my code.

Now my problem. I have set the chart to display only the last 20 seconds of the chart. So the count of points which have to be drawn are always the same. And chart repainting is set to 10 seconds.
This works nice and it starts with a very low CPU usage. But after running the application over night I got a CPU usage by ~70%. In this time there where ~150000 points added to each TFastLineSeries.

So my question is ... Why is the CPU usage so high? I thought it would always be constant because we only draw the same amount of points to the chart.

Can you think of any improvements to have a constant CPU usage? I can´t imagine that the CPU usage get higher because of adding more data to the chart.

Hope you can give me a hint because this is a really big problem for long term data rcordings.

Greetz Dominik

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: Speed up Live Plotting?

Post by Narcís » Wed Nov 11, 2009 9:04 am

Hi Dominik,
So my question is ... Why is the CPU usage so high? I thought it would always be constant because we only draw the same amount of points to the chart.
Even if you are displaying a little amount of points your series may need to handle a huge amount of data which can lead to memory consumption and CPU usage. Are you removing the points that are not being displayed?
Can you think of any improvements to have a constant CPU usage? I can´t imagine that the CPU usage get higher because of adding more data to the chart.
Yes, I strongly recommend you to read the Real-time Charting article here and apply as many of the hints there in your project as possible.

Hope this helps!
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Wed Nov 11, 2009 9:58 am

Hi Narcis,
Yes, I strongly recommend you to read the Real-time Charting article here and apply as many of the hints there in your project as possible.
I read that text several times :)
Are you removing the points that are not being displayed?
No.
Could you explain me the function of [Series].Delete? Will it delete the points completly from the series / chart? Or is it used only internaly to reduce the number of points which are calculated for the view?

Or in other words ... If I call .delete(0,100) ... Will I lose the first 100 points completely?

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: Speed up Live Plotting?

Post by Narcís » Wed Nov 11, 2009 10:02 am

Hi Dominik,
Or in other words ... If I call .delete(0,100) ... Will I lose the first 100 points completely?
Yes.

If mentioned article doesn't help can you please attach a simple example project we can run "as-is" and let us know the exact steps we should follow to reproduce the issue here so that we can suggest some suitable solution?

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Wed Nov 11, 2009 10:35 am

Hi Narcis,

well ... delete data is no option. We want to keep all the data.
Think about a weather station logging software. It would be not a good idea to delete the old data .... :?

I will prepare a demo for you.

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Wed Nov 11, 2009 10:50 am

Hi Narcis,

I´ve uploaded a demo project:
Received Plotting - CPU usage.zip Content Type application/x-zip-compressed Length 7539

As I wrote before ... The problem is that after a while the CPU usage raises.

It would be great if you can show us a methode to kepp the CPU usage down even if you log a lot of data.
And it is no option to delete data. That´s absolutely impossible in our application.

Thx a lot for your help !

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Thu Nov 12, 2009 1:05 pm

Hi Narcis,

could you examine some improvements in my demo?

Yeray
Site Admin
Site Admin
Posts: 9614
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Speed up Live Plotting?

Post by Yeray » Thu Nov 12, 2009 4:03 pm

Hi Dominik,

Why don't you save your data in a file or several files each x seconds so that the old data can be safely removed from the series?
As Narcís indicated, this limit is more cause of the drawing machine than TeeChart itself.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Fri Nov 13, 2009 5:58 am

Hi !
Why don't you save your data in a file or several files each x seconds so that the old data can be safely removed from the series?
Sorry but did you take a look at my demo code? We use TChart for live plotting and a floating X axis is only one option to reduce the CPU load. As I said before - deleting of points is no option for us because our user need the possibility to view all recorded data, too. If I save some data to extra files I need to handle that - maybe while still plotting. The CPU usage would be more increased then just running the chart with all data.
As Narcís indicated, this limit is more cause of the drawing machine than TeeChart itself.
Drawing mashine means the computer I´m running my demo?
For sure - I use that computer to detect such CPU related problems.
Even if you are displaying a little amount of points your series may need to handle a huge amount of data which can lead to memory consumption and CPU usage.
Could you be a little bit more precise? What needs to be handled with the data which is not shown?

I hope you can take a look at my demo code I send to you. Actually I can't believe that ~300000 points of data (where only the last ~10 points are plotted -> Floating is checked in my demo) need ~36% of my CPU.

Thx for your help

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Fri Nov 13, 2009 10:55 am

Hi Narcis, Hi Yeray ...

I took a deeper look into the procedure "ADDXY" and properbly I found the CPU killing position ...

Unit TeEngine
procedure TChartValueList.RecalcStats(StartIndex:Integer);

There is this piece of code (I hope it is ok to post it here ...):

Code: Select all

    for t:=StartIndex+tmpOffset to Count-1 do  // 7.01
    Begin
      tmpValue:=Value[t];

      if tmpValue<FMinValue then FMinValue:=tmpValue else
      if tmpValue>FMaxValue then FMaxValue:=tmpValue;

      FTotal:=FTotal+tmpValue;
      FTotalABS:=FTotalABS+Abs(tmpValue);
    end;
This code is executed every time you add a simple value to the series. Even if I change the bottom axis (min max value) this code is executed.
But I have no idea whats the exact sense of this code ...

Wouldn´t it be enough to calculate the Min / Max values only for the added point like this:

Code: Select all

      tmpValue:=Value[count -1];
if tmpValue<FMinValue then FMinValue:=tmpValue else
      if tmpValue>FMaxValue then FMaxValue:=tmpValue;
Same for FTotal, FTotalABS. Why must there be a For / Next loop which calculates the values always from the beginning of the chart? Wouldn´t it be enough to only calculate the last two values?

Now it becomes more clear to me why there is such a high CPU load after adding a lot of points to the series ....

The big question is ... What can be done?

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Fri Nov 13, 2009 11:17 am

Hi @all,

it´s me again :)

If I change the code:

Code: Select all

    for t:=StartIndex+tmpOffset to Count-1 do  // 7.01
    Begin
      tmpValue:=Value[t];

      if tmpValue<FMinValue then FMinValue:=tmpValue else
      if tmpValue>FMaxValue then FMaxValue:=tmpValue;

      FTotal:=FTotal+tmpValue;
      FTotalABS:=FTotalABS+Abs(tmpValue);
    end;
to this:

Code: Select all

    if StartIndex+tmpOffset <= Count-1 then
    Begin
      tmpValue:=Value[Count-1];

      if tmpValue<FMinValue then FMinValue:=tmpValue else
      if tmpValue>FMaxValue then FMaxValue:=tmpValue;

      FTotal:=FTotal+tmpValue;
      FTotalABS:=FTotalABS+Abs(tmpValue);
    end;
all works still fine. And it increases the speed (even with hugh amount of data) alot !

But I can not estimate the impact to other parts of the whole engine. I only did a test with TFastLineSeries.

What do you think about my suggestion?

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Fri Nov 13, 2009 11:47 am

Hi !

Ok I found one problem ... The Axis ranges are not correct with my code.
But I think this could be fixed easily.

Code: Select all

    FMaxValue    : TChartValue;
    FMinValue    : TChartValue;
    FTotal       : Double;
    FTotalABS    : Double;
These variables should store the last value. Or you add 4 extra variables which store the last value. Then my code would work perfect.

And it would end in a dramatic speedup of the engine !

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Re: Speed up Live Plotting?

Post by moelski » Fri Nov 13, 2009 1:19 pm

Hi !

Another hour of code analyzing ... :wink:

Why don´t you add these variables to the class TChartValueList=class(TPersistent)

Code: Select all

FMaxValue    : TChartValue;
FMinValue    : TChartValue;
FTotal       : Double;
FTotalABS    : Double;
If a point is added you can make very easy calculations without running through a FOR NEXT construct.

This could be done in
Function AddChartValue(Const AValue:TChartValue):Integer; overload; virtual;
Procedure InsertChartValue(ValueIndex:Integer; Const AValue:TChartValue); virtual;

What do you think?

moelski
Newbie
Newbie
Posts: 92
Joined: Tue Jun 19, 2007 12:00 am
Contact:

Suggestion for a solution !

Post by moelski » Sun Nov 15, 2009 8:45 am

Hi @all,

finally I made some changes to TeEngine.pas which results in extrem speedup.

@Narcis / Yeray:
I uploaded my TeEngine.pas:
Received TeEngine.pas Content Type application/octet-stream Length 399567
My changes are marked with {DS}.

Actually there are 4 positions changed:
Constructor TChartValueList.Create
Procedure TChartValueList.InsertChartValue
Function TChartValueList.AddChartValue:
procedure TChartValueList.RecalcStats

I have also made a video which shows the speedup. The comments are in german, but I´ve added a lot callouts in english. So you will understand the contense :wink:

You can download the video here:
http://www.logview.info/videos/Speedplotting.zip

Please take a look at this problem. Maybe my fix is not the best (and may introduce problems) but I think the originial code is useless if you need to plot a hugh mount of data. And as you can see it is possible to plot millions of points with TChart without overheating the CPU ...

Hope to hear from you.

Greetings
Dominik

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: Speed up Live Plotting?

Post by Narcís » Mon Nov 16, 2009 10:47 am

Hi Dominik

Thanks for your efforts and feedback. We are investigating if your suggestion can be implemented in TeeChart's sources. We will get back to you when we have further news.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Post Reply