Performance Issue with Grid Lines and PenStyle psDot

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
ags
Newbie
Newbie
Posts: 2
Joined: Wed May 18, 2022 12:00 am

Performance Issue with Grid Lines and PenStyle psDot

Post by ags » Thu Dec 19, 2024 9:43 am

Hello Steema Support,

I am experiencing significant performance degradation when enabling minor grid lines in TChart. Here are the details:
- TChart Version: 2023.38.230607
- Delphi Version: Delphi 11
- Operating System: Windows 11 Enterprise

Description:
When I enable minor grid lines in a TChart, the chart's rendering performance drops significantly. This is an issue when we do realtime redraws on mousemove events (see example) and in general when redrawing multiple/big charts.

Steps to Reproduce:
1. Create a new VCL Forms Application in Delphi.
2. Add the code provided below
3. run the app in 64-bit, maximized (in full screen) (performance is the same in 32-bit, but that is not our usecase)
4. Move the mouse into the chart, and the last point in the fastlineseries will follow the movement of the mouse.
5. Use mouse button click to add points to the chart. The display of minor grid lines will be switched on/off every time you click to add a point.
6. Observe the performance degradation when the chart is rendered with minor grid lines visible and you move the mouse.

Sample Code:

Code: Select all

uses
  VCLTee.Chart, VCLTee.TeEngine, VCLTee.Series;

var
  Chart1: TChart;
  FastLineSeries: TFastLineSeries;

procedure TForm1.AddFastLineSeriesToPlot;
begin
  FastLineSeries := TFastLineSeries.Create(nil);
  FastLineSeries.XValues.Order := loNone;
  FastLineSeries.YValues.Order := loNone;
  FastLineSeries.LinePen.OwnerCriticalSection := nil; // single threaded
  FastLineSeries.LinePen.Style := psSolid;
  FastLineSeries.LinePen.Width := 5;
  FastLineSeries.Color := clRed;
  FastLineSeries.AutoRepaint := False;
  Chart1.AddSeries(FastLineSeries);
end;

procedure TForm1.ShowHideMinorGrid;
var
  MinorGridVisible: Boolean;
begin
  if FastLineSeries.XValues.Count > 0 then begin
    MinorGridVisible := Odd(FastLineSeries.XValues.Count);
    Chart1.BottomAxis.MinorGrid.Visible := MinorGridVisible;
    Chart1.LeftAxis.MinorGrid.Visible := MinorGridVisible;
  end;
end;

procedure TForm1.AddPoint(MouseX, MouseY: Integer);
var
  X: Double;
  Y: Double;
begin
  X := Chart1.BottomAxis.CalcPosPoint(MouseX);
  Y := Chart1.LeftAxis.CalcPosPoint(MouseY);
  FastLineSeries.AddXY(X, Y);
  FastLineSeries.Repaint;
end;

procedure TForm1.MoveLastPoint(MouseX, MouseY : Integer);
var
  Index: Integer;
begin
  if FastLineSeries.XValues.Count > 0 then begin
    Index := FastLineSeries.XValues.Count - 1;
    FastLineSeries.XValues[Index] := Chart1.BottomAxis.CalcPosPoint(MouseX);
    FastLineSeries.YValues[Index] := Chart1.LeftAxis.CalcPosPoint(MouseY);
    FastLineSeries.Repaint;
  end;
end;

procedure TForm1.Chart1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  AddPoint(X, Y);
  ShowHideMinorGrid;
end;

procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  MoveLastPoint(X, Y);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1 := TChart.Create(Self);

  Chart1.Parent := Self;
  Chart1.Align := alClient;
  Chart1.View3D := False;
  Chart1.Legend.Visible := False;
  Chart1.ClipPoints := False;
  Chart1.Canvas.ReferenceCanvas.Pen.OwnerCriticalSection := nil; // single threaded
  Chart1.Axes.FastCalc := True;

  Chart1.BottomAxis.SetMinMax(0, 100);
  Chart1.LeftAxis.SetMinMax(0, 10);

  Chart1.OnMouseDown := Chart1MouseDown;
  Chart1.OnMouseMove := Chart1MouseMove;
  // major grid
  Chart1.BottomAxis.Grid.Visible := True;
  Chart1.BottomAxis.Grid.Style := psSolid;
  Chart1.BottomAxis.Grid.Width := 2;
  Chart1.BottomAxis.Grid.Color := clLtGray;
  Chart1.LeftAxis.Grid.Visible := True;
  Chart1.LeftAxis.Grid.Style := psSolid;
  Chart1.LeftAxis.Grid.Width := 2;
  Chart1.LeftAxis.Grid.Color := clLtGray;
  // minor grid
  Chart1.BottomAxis.MinorGrid.Visible := False;
  Chart1.BottomAxis.MinorGrid.Style := psDot;
  Chart1.BottomAxis.MinorGrid.Width := 1;
  Chart1.BottomAxis.MinorGrid.Color := clLtGray;
  Chart1.LeftAxis.MinorGrid.Visible := False;
  Chart1.LeftAxis.MinorGrid.Style := psDot;
  Chart1.LeftAxis.MinorGrid.Width := 1;
  Chart1.LeftAxis.MinorGrid.Color := clLtGray;

  AddFastLineSeriesToPlot;
  AddPoint(10, 10);
end;

I would appreciate any advice or solutions you can provide to improve the performance when minor grid lines are enabled.

Thank you,
Ags


Update:
After further investigation the cause of the performance issue is narrowed down to the PenStyle:
Chart1.LeftAxis.MinorGrid.Style := psDot; // is slow
Chart1.LeftAxis.MinorGrid.Style := psSolid; // is fast
However that means that the performance issue is also observed if psDot is used for the major grid lines:
Chart1.LeftAxis.Grid.Style := psDot; // is slow

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

Re: Performance Issue with Grid Lines and PenStyle psDot

Post by Yeray » Fri Dec 20, 2024 8:27 am

Hello,

I'm afraid GDIPlus is slow at drawing dashed lines. However, moving to OpenGL may be a good option for you.
In that project, just add TeeGLCanvas to the uses clause and initialize the canvas at the end of your FormCreate:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
begin
  //...
  Chart1.Canvas:=TGLCanvas.Create;
end;
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

Post Reply