Performance Comparing Delphi tCanvas with .Net Graphics

236 views Asked by At

I use Delphi 10.3 and .Net 5.0. I know tCanvas is GDI and Graphics is GDI+ which outperforms the former. But in the following simple codes tCanvas is faster. The 5 times average milliseconds of Delphi is 185.00 and .Net is 351.20.

Why is tCanvas faster than Graphics, or is there any flaw in my codes?

Delphi

procedure TForm1.PaintBox1Click(Sender: TObject);
var
  _Rectangle: TRect;
  _Rectangles: TList<TRect>;
  _Stopwatch: TStopwatch;
  i: Integer;
begin
  PaintBox1.Canvas.Brush.Color := clWhite;

  _Rectangle.Left := 0;
  _Rectangle.Top := 0;
  _Rectangle.Width := PaintBox1.Width;
  _Rectangle.Height := PaintBox1.Height;

  PaintBox1.Canvas.FillRect(_Rectangle);

  _Rectangles := TList<TRect>.Create;

  for i := 0 to 9999 do
  begin
    _Rectangle.Left := Random(1000);
    _Rectangle.Top := Random(1000);
    _Rectangle.Right := _Rectangle.Left + 5;
    _Rectangle.Bottom := _Rectangle.Top + 5;

    _Rectangles.Add(_Rectangle);
  end;

  PaintBox1.Canvas.Brush.Color := clBlack;

  _Stopwatch := TStopwatch.StartNew;

  for i := 0 to 9999 do
  begin
    PaintBox1.Canvas.FillRect(_Rectangles.List[i]);
  end;

  Caption := IntToStr(_Stopwatch.ElapsedMilliseconds);

  _Rectangles.Free;
end;

.Net

private void panel1_Click(object sender, EventArgs e)
{
    Graphics _Graphics = panel1.CreateGraphics();
    List<Rectangle> _Rectangles = new();
    Random _Random = new();
    Rectangle _Rectangle = new(0, 0, panel1.Width, panel1.Height);
    SolidBrush _SolidBrush = new(Color.White);

    _Graphics.FillRectangle(_SolidBrush, _Rectangle);

    for (int i = 0; i < 10000; i++)
    {
        _Rectangle = new(_Random.Next(1000), _Random.Next(1000), 5, 5);

        _Rectangles.Add(_Rectangle);
    }

    _SolidBrush.Color = Color.Black;

    Stopwatch _Stopwatch = new();

    _Stopwatch.Start();

    foreach (var item in _Rectangles)
    {
        _Graphics.FillRectangle(_SolidBrush, item);
    }

    Text = _Stopwatch.ElapsedMilliseconds.ToString();

    _Graphics.Dispose();
    _SolidBrush.Dispose();
}
1

There are 1 answers

0
SHIN JaeGuk On BEST ANSWER

Following David's advice, using Bitmap enhanced the performance much to 48.2 milliseconds.

private void button1_Click(object sender, EventArgs e)
{
    Bitmap _Bitmap = new(1000, 1000);

    Graphics _BitmapGraphics = Graphics.FromImage(_Bitmap);
    Graphics _PanelGraphics = panel1.CreateGraphics();
    List<Rectangle> _Rectangles = new();
    Rectangle _Rectangle;
    Random _Random = new();
    SolidBrush _SolidBrush = new(Color.Black);

    _BitmapGraphics.Clear(Color.White);

    for (int i = 0; i < 10000; i++)
    {
        _Rectangle = new(_Random.Next(1000), _Random.Next(1000), 5, 5);

        _Rectangles.Add(_Rectangle);
    }

    Stopwatch _Stopwatch = new();

    _Stopwatch.Start();

    foreach (var item in _Rectangles)
    {
        _BitmapGraphics.FillRectangle(_SolidBrush, item);
    }

    _PanelGraphics.DrawImage(_Bitmap, Point.Empty);
        
    button1.Text = _Stopwatch.ElapsedMilliseconds.ToString();

    _Bitmap.Dispose();
    _BitmapGraphics.Dispose();
    _PanelGraphics.Dispose();
    _SolidBrush.Dispose();
}