A list is much faster, a dynamic array uses less resources, except when it needs to insert, delete, copy: 2 X the size for every insertion or delete..
A simple test does not appear to bear this assertion out.
The test program I used is given below. It is followed by typical output.
The tick counts seem reliable.I have not tested the performance of random inserts and deletes, merely allocating and filling the container, and then deallocating the memory used.
I may not be calculating the memory usages properly, however, so if someone thinks the following needs correcting, please do.
At 200,000 items the array and the list are indistinguishable in performance and memory use as far as I can see.
program ListVersusDynarray;
{$mode objfpc}{$H+}
uses
contnrs, Classes, sysutils;
type
{ TTest }
TTest = class(TObject)
public
Number: Int64;
Float: Double;
Name: AnsiString;
constructor Create(aNumber: Int64);
function GetMemSize: PtrUInt;
end;
TTestDynArray = array of TTest;
function MemSizeAnsiString(const aStr: AnsiString): PtrUInt;
begin
Result := Length(aStr);
if Length(aStr) > 0 then
Inc(Result, SizeOf(Pointer)*4);
end;
function MemSizeObjList(const aList: TFPObjectList): PtrUInt;
var
i: Integer;
begin
case Assigned(aList) of
False: Exit(0);
True: begin
Result := PtrUInt(aList.InstanceSize);
for i := 0 to aList.Count-1 do
Inc(Result, TTest(aList[i]).GetMemSize);
end;
end;
end;
function MemSizeTestDynarray(const anArray: TTestDynArray): PtrUInt;
var
test: TTest;
begin
Result := SizeOf(Pointer)*4;
for test in anArray do
Inc(Result, test.GetMemSize);
end;
type
TContainerKind = (ckArray, ckList);
{ TComparer }
TComparer = class(TObject)
private
FList: TFPObjectList;
FArray: TTestDynArray;
public
constructor Create;
function SetupTearDownTicks(itemCount: DWORD; aContainerKind: TContainerKind; out memSize: PtrUInt): DWord;
end;
{ TTest }
constructor TTest.Create(aNumber: Int64);
begin
Number := aNumber;
Float := aNumber;
Str(Float:14:2, Name);
end;
function TTest.GetMemSize: PtrUInt;
begin
Exit(PtrUInt(InstanceSize) + SizeOf(Number) + SizeOf(Float) + MemSizeAnsiString(Name));
end;
{ TComparer }
constructor TComparer.Create;
begin
Randomize;
end;
function TComparer.SetupTearDownTicks(itemCount: DWORD;
aContainerKind: TContainerKind; out memSize: PtrUInt): DWord;
var
start: QWord;
i: DWord;
begin
case aContainerKind of // measure memory allocated
ckArray: begin
SetLength(FArray, itemCount);
for i := 0 to itemCount-1 do
FArray[i] := TTest.Create(Random(itemCount));
memSize := MemSizeTestDynarray(FArray);
for i := 0 to itemCount-1 do
FArray[i].Free;
SetLength(FArray, 0);
end;
ckList: begin
FList := TFPObjectList.Create(True);
FList.Capacity := itemCount;
for i := 0 to itemCount-1 do
FList.Add(TTest.Create(Random(itemCount)));
memSize := MemSizeObjList(FList);
FList.Free;
end;
end;
start := GetTickCount64; // measure ticks elapsed for allocation/deallocation
case aContainerKind of
ckArray: begin
SetLength(FArray, itemCount);
for i := 0 to itemCount-1 do
FArray[i] := TTest.Create(Random(itemCount));
for i := 0 to itemCount-1 do
FArray[i].Free;
SetLength(FArray, 0);
end;
ckList: begin
FList := TFPObjectList.Create(True);
FList.Capacity := itemCount;
for i := 0 to itemCount-1 do
FList.Add(TTest.Create(Random(itemCount)));
FList.Free;
end;
end;
Result := GetTickCount64 - start;
end;
var
comparer: TComparer;
count: DWord;
ck: TContainerKind;
i: Integer;
sz: PtrUInt;
begin
comparer := TComparer.Create;
for i := 1 to 10 do
begin
count := i * 20000;
for ck in TContainerKind do
WriteLn('count=',count:6,' for ',ck:8,': ',comparer.SetupTearDownTicks(count, ck, sz):3,' ticks; memory used=',sz);
end;
comparer.Free;
ReadLn;
end.
Typical output:
count= 20000 for ckArray : 26 ticks; memory used=1880032
count= 20000 for ckList : 25 ticks; memory used=1880024
count= 40000 for ckArray : 50 ticks; memory used=3760032
count= 40000 for ckList : 49 ticks; memory used=3760024
count= 60000 for ckArray : 75 ticks; memory used=5640032
count= 60000 for ckList : 73 ticks; memory used=5640024
count= 80000 for ckArray : 99 ticks; memory used=7520032
count= 80000 for ckList : 97 ticks; memory used=7520024
count=100000 for ckArray : 123 ticks; memory used=9400032
count=100000 for ckList : 122 ticks; memory used=9400024
count=120000 for ckArray : 148 ticks; memory used=11280032
count=120000 for ckList : 146 ticks; memory used=11280024
count=140000 for ckArray : 172 ticks; memory used=13160032
count=140000 for ckList : 170 ticks; memory used=13160024
count=160000 for ckArray : 196 ticks; memory used=15040032
count=160000 for ckList : 195 ticks; memory used=15040024
count=180000 for ckArray : 221 ticks; memory used=16920032
count=180000 for ckList : 219 ticks; memory used=16920024
count=200000 for ckArray : 245 ticks; memory used=18800032
count=200000 for ckList : 244 ticks; memory used=18800024