program stringlistperformancetest;
{$MODE ObjFpc}
{$H+}

uses
  SysUtils, Classes;

type
  PRec = ^TRec;
  TRec = record
    Selected:Boolean;
    Number:Integer;
  end;

  TMyClass = class(TObject)
    private
      FNumber: Integer;
      FSelected: Boolean;
    public
      property Selected: Boolean read FSelected write FSelected;
      property Number: Integer read FNumber write FNumber;
  end;

const
  MAX_RUNS = 30000000;

var
  sl: TStringList;
  RunStart, RunEnd: Int64;
  MemorySize: Int64;

function TestObjects: Int64;
var
  i: Int64;
  o: TMyClass;
begin
  Result := 0;
  for i := 0 to MAX_RUNS do begin
    o := TMyClass.Create;
    o.Selected := True;
    o.Number := i;
    sl.AddObject('Test', o);
    Result := Result + MemSize(o);
  end;
  for i := 0 to MAX_RUNS do begin
    o := TMyClass(sl.Objects[i]);
    if o.Selected then
      o.Free;
  end;
end;

function TestRecords: Int64;
var
  i: Int64;
  r: PRec;
begin
  Result := 0;
  for i := 0 to MAX_RUNS do begin
    New(r);
    r^.Selected := True;
    r^.Number := i;
    sl.AddObject('Test', TObject(r));
    Result := Result + MemSize(r);
  end;
  for i := 0 to MAX_RUNS do begin
    r := PRec(sl.Objects[i]);
    if r^.Selected then
      Dispose(r);
  end;
end;


begin
  WriteLn('Testing with class...');
  sl := TStringList.Create;
  RunStart := GetTickCount64;
  MemorySize := TestObjects;
  RunEnd := GetTickCount64;
  FreeAndNil(sl);
  WriteLn('... ', RunEnd - RunStart, ' ms (', ((RunEnd - RunStart) / MAX_RUNS):0:10, ' ms/object), using ', MemorySize, ' bytes.');

  WriteLn;

  WriteLn('Testing with record...');
  sl := TStringList.Create;
  RunStart := GetTickCount64;
  MemorySize := TestRecords;
  RunEnd := GetTickCount64;
  FreeAndNil(sl);
  WriteLn('... ', RunEnd - RunStart, ' ms (', ((RunEnd - RunStart) / MAX_RUNS):0:10, ' ms/record), using ', MemorySize, ' bytes.');
end.

