Page 1 of 1

Performance Issue with Grid Lines and PenStyle psDot

Posted: Thu Dec 19, 2024 9:43 am
by 16593767
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

Re: Performance Issue with Grid Lines and PenStyle psDot

Posted: Fri Dec 20, 2024 8:27 am
by yeray
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;