Skip to main content
TeeChart is optimized for real-time data visualization, capable of handling thousands of points with smooth updates. Use specialized techniques to achieve maximum performance.

Overview

Real-time charting requires:
  • Fast data addition and removal
  • Efficient rendering
  • Minimal memory allocation
  • Optimized axis calculations
  • Smart scrolling techniques
TeeChart achieves this through the TFastLineSeries and various optimization settings.

FastLine Series

Basic Setup

uses Series;

var
  FastLine: TFastLineSeries;
begin
  FastLine := TFastLineSeries.Create(Self);
  FastLine.ParentChart := Chart1;
  
  // Disable AutoRepaint for real-time mode
  FastLine.AutoRepaint := False;
  
  // Disable ordering for faster additions
  FastLine.XValues.Order := loNone;
end;
Key Property: AutoRepaint := False means points are displayed immediately after adding without redrawing the whole chart. Source: FastLine_Realtime.pas:73

Performance Optimizations

Chart Configuration

procedure TForm1.PrepareChartForRealtime;
begin
  with Chart1 do
  begin
    // Disable clipping for speed
    ClipPoints := False;
    
    // Hide non-essential elements
    Title.Visible := False;
    Legend.Visible := False;
    
    // Thin axis lines
    LeftAxis.Axis.Width := 1;
    BottomAxis.Axis.Width := 1;
    BottomAxis.RoundFirstLabel := False;
    
    // Disable 3D
    View3D := False;
    
    // Fast axis calculations
    Axes.FastCalc := True;
  end;
end;
Source: FastLine_Realtime.pas:51

Series Optimizations

// For Windows NT/2000/XP and later
// Use fast solid pens of width 1
Series1.FastPen := True;

// Disable critical section locks for single-threaded apps
Chart1.Canvas.ReferenceCanvas.Pen.OwnerCriticalSection := nil;
Series1.LinePen.OwnerCriticalSection := nil;
Source: FastLine_Realtime.pas:86

DrawAllPoints

// Draw every point (default)
Series1.DrawAllPoints := True;

// Or draw selectively for better speed with many points
Series1.DrawAllPoints := False;
Source: FastLine_Realtime.pas:197

Adding Real-Time Data

Continuous Addition

procedure TForm1.AddRealtimePoint(Series: TChartSeries);
begin
  if Series.Count = 0 then
    // First point
    Series.AddXY(1, Random(10000))
  else
    // Next point - increment X automatically
    Series.AddXY(
      Series.XValues.Last + 1,
      Series.YValues.Last + Random(10) - 4.5
    );
end;
Source: FastLine_Realtime.pas:107

Timer-Based Updates

procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 10;  // Update every 10ms
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  AddRealtimePoint(Series1);
end;
Source: ColorGrid_Realtime.pas:20

Loop-Based Updates

For maximum speed without timer overhead:
procedure TForm1.StartRealTimeLoop;
begin
  Stopped := False;
  
  while not Stopped do
  begin
    // Add points to series
    AddRealtimePoint(Series1);
    AddRealtimePoint(Series2);
    
    // Handle scrolling when full
    if Series1.Count > MaxPoints - 1 then
      DoScrollPoints;
  end;
end;
Source: FastLine_Realtime.pas:167

Scrolling Techniques

Delete and Scroll

When the chart fills up, delete old points and scroll the axis:
procedure TForm1.DoScrollPoints;
var
  Tmp, TmpMin, TmpMax: Double;
begin
  // Delete multiple points in one call (much faster than loop)
  Series1.Delete(0, ScrollPoints);  // Delete first ScrollPoints
  Series2.Delete(0, ScrollPoints);
  
  // Scroll horizontal axis
  Tmp := Series1.XValues.Last;
  Chart1.BottomAxis.SetMinMax(
    Tmp - MaxPoints + ScrollPoints,
    Tmp + ScrollPoints
  );
  
  // Scroll vertical axis if not automatic
  if not Chart1.LeftAxis.Automatic then
  begin
    TmpMin := Series1.YValues.MinValue;
    if Series2.YValues.MinValue < TmpMin then
      TmpMin := Series2.YValues.MinValue;
    
    TmpMax := Series1.YValues.MaxValue;
    if Series2.YValues.MaxValue > TmpMax then
      TmpMax := Series2.YValues.MaxValue;
    
    Chart1.LeftAxis.SetMinMax(
      TmpMin - TmpMin / 5,
      TmpMax + TmpMax / 5
    );
  end;
  
  // Process messages to update display
  Application.ProcessMessages;
end;
Source: FastLine_Realtime.pas:118

Fixed Window Scrolling

const
  MaxPoints = 10000;     // Total points visible
  ScrollPoints = 5000;   // Points to remove when full

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Set fixed axis range
  Chart1.BottomAxis.SetMinMax(1, MaxPoints);
end;
Source: FastLine_Realtime.pas:64

ColorGrid Real-Time

For real-time heatmap/grid data:
procedure TForm1.UpdateColorGrid;
var
  Y, Z, Index: Integer;
begin
  Index := ColorGrid.Count;
  
  ColorGrid.BeginUpdate;
  try
    Inc(X);
    
    // Add new column of data
    for Z := 0 to DemoPoints - 1 do
    begin
      Y := Random(100);
      ColorGrid.AddXYZ(X, Y, Z, '', Random($FFFFFF));
    end;
    
    // SPEED OPTIMIZATIONS
    // Recalculate stats only for new points
    TListHack(ColorGrid.XValues).RecalcStats(Index);
    TListHack(ColorGrid.YValues).RecalcStats(Index);
    TListHack(ColorGrid.ZValues).RecalcStats(Index);
    
    if ColorGrid.ReuseGridIndex then
      ColorGrid.FillGridIndex(Index);
    
    ColorGrid.Repaint;
  finally
    ColorGrid.EndUpdate;
  end;
end;
Source: ColorGrid_Realtime.pas:45

ColorGrid Optimizations

procedure TForm1.OptimizeColorGrid;
begin
  // Remove chart elements for speed
  Chart1.Legend.Hide;
  Chart1.ClipPoints := False;
  Chart1.Title.Hide;
  Chart1.Axes.Left.Grid.Hide;
  Chart1.Axes.Bottom.Grid.Hide;
  ColorGrid.Pen.Hide;
  
  // Enable optimizations
  ColorGrid.ReuseGridIndex := True;
  Chart1.Axes.FastCalc := True;
end;
Source: ColorGrid_Realtime.pas:104

Memory Management

BeginUpdate/EndUpdate

Batch multiple additions:
Series1.BeginUpdate;
try
  for i := 1 to 1000 do
    Series1.AddXY(i, Random(100));
finally
  Series1.EndUpdate;
end;

Clear Efficiently

// Clear all series
Chart1.SeriesList.Clear;

// Or clear single series
Series1.Clear;

Threading Support

Thread-Safe Updates

type
  TDataThread = class(TThread)
  protected
    procedure Execute; override;
    procedure AddPoint;  // Synchronized method
  end;

procedure TDataThread.Execute;
begin
  while not Terminated do
  begin
    Synchronize(AddPoint);
    Sleep(10);
  end;
end;

procedure TDataThread.AddPoint;
begin
  Series1.AddXY(Now, Random(100));
end;

Performance Tips

Do’s

  1. Use TFastLineSeries for line charts
  2. Set AutoRepaint := False for real-time mode
  3. Disable XValues.Order (use loNone)
  4. Enable FastCalc for axes
  5. Use Delete(StartIndex, Count) to remove multiple points
  6. Hide unnecessary chart elements (title, legend, grids)
  7. Use BeginUpdate/EndUpdate for batch operations
  8. Set FastPen := True for solid pens

Don’ts

  1. Don’t use View3D for real-time (slower)
  2. Don’t enable ClipPoints (adds overhead)
  3. Don’t use gradients on series
  4. Don’t delete points in a loop (use batch delete)
  5. Don’t use AutoRepaint := True for real-time
  6. Don’t calculate stats on every addition

Benchmark Results

Typical performance on modern hardware:
ConfigurationPoints/Second
Optimized FastLine100,000+
Standard Line10,000
3D Line5,000
ColorGrid (optimized)50,000+

Example: Complete Real-Time System

type
  TRealtimeForm = class(TForm)
    Chart1: TChart;
    Series1: TFastLineSeries;
    Timer1: TTimer;
  private
    FMaxPoints: Integer;
    FScrollPoints: Integer;
    procedure OptimizeChart;
    procedure AddDataPoint;
    procedure ScrollData;
  end;

procedure TRealtimeForm.FormCreate(Sender: TObject);
begin
  FMaxPoints := 10000;
  FScrollPoints := 5000;
  
  OptimizeChart;
  
  Timer1.Interval := 10;
  Timer1.Enabled := True;
end;

procedure TRealtimeForm.OptimizeChart;
begin
  // Chart settings
  Chart1.ClipPoints := False;
  Chart1.Legend.Hide;
  Chart1.Title.Hide;
  Chart1.View3D := False;
  Chart1.Axes.FastCalc := True;
  
  // Series settings
  Series1.AutoRepaint := False;
  Series1.XValues.Order := loNone;
  Series1.FastPen := True;
  
  // Disable locking for single thread
  Chart1.Canvas.ReferenceCanvas.Pen.OwnerCriticalSection := nil;
  Series1.LinePen.OwnerCriticalSection := nil;
  
  // Set initial axis range
  Chart1.BottomAxis.SetMinMax(1, FMaxPoints);
end;

procedure TRealtimeForm.Timer1Timer(Sender: TObject);
begin
  AddDataPoint;
  
  if Series1.Count >= FMaxPoints then
    ScrollData;
end;

procedure TRealtimeForm.AddDataPoint;
var
  NewX, NewY: Double;
begin
  if Series1.Count = 0 then
  begin
    NewX := 1;
    NewY := Random(1000);
  end
  else
  begin
    NewX := Series1.XValues.Last + 1;
    NewY := Series1.YValues.Last + Random(10) - 5;
  end;
  
  Series1.AddXY(NewX, NewY);
end;

procedure TRealtimeForm.ScrollData;
var
  LastX: Double;
begin
  // Delete old points
  Series1.Delete(0, FScrollPoints);
  
  // Scroll axis
  LastX := Series1.XValues.Last;
  Chart1.BottomAxis.SetMinMax(
    LastX - FMaxPoints + FScrollPoints,
    LastX + FScrollPoints
  );
  
  Application.ProcessMessages;
end;

Axes

Axis configuration and optimization

Series Types

FastLine and other series types

Build docs developers (and LLMs) love