我可以在您的列表中添加另一个选择吗?
如果您不对 中的数据使用任何继承功能,则TAtom
可以使用 arecord
而不是 a class
。每个类实例都需要在内存中分配,用零填充并单独初始化。Getmem/Freemem
总是成本,并且内存碎片会增加。
预先分配的动态array of record
将比添加单个类实例更快。并且数据将更适合 CPU L1/L2 缓存。
对于插入和删除,这样的记录数组将比TList
拥有大量项目时要慢,因为要删除/插入的数据更多(TList/TObjectList
两者都只维护一个指针列表)。为了更快地插入/删除,您应该更好地使用链表。
TList/TObjectList
由于内部通知,该机制存在一些开销。机制并且该GetItem()
属性可能比直接使用动态数组要慢一些(因为范围检查)。
但是使用我们的TDynArray 包装器,您可以坚持使用动态数组,并且仍然具有良好的性能、预分配功能和TList
类似的方法。还有更多可用的方法,比如SaveToStream, Slice, Reverse
使用外部索引排序等等......
type
TAtom = record // could be 'packed record' to save memory (but loose perf)
ElementZ: Integer;
X, Y, Z: Extended;
other variables: other types;
// TDynArray also handle complex (e.g. string) types here
end;
TAtoms = array of TAtom;
var Atom: TAtom;
AtomArray: TAtoms;
AtomCount: integer;
Atoms: TDynArray;
begin
Atoms.Init(TypeInfo(TAtoms),AtomArray,@AtomCount);
Atoms.Capacity := 10000; // pre-allocate array = same as SetLength(AtomArray,10000)
for i := 1 to 10000 do begin
A.ElementZ := Random(1000);
A.X := Random;
A.Y := Ramdom;
A.Z := Random;
// set other fields
Atoms.Add(A); // fast adding of A properties
end;
// you have TList-like methods for your dynamic array
Atoms.Delete(500); // delete 500th item
A.ElementZ := 5000;
Atoms.Insert(500,A); // insert A values at 500th index
assert(Atoms.Count=10000);
assert(AtomCount=10000); // same as Atoms.Count
Atoms.Compare := SortDynArrayInteger;
Atoms.Sort; // will sort by 1st Integer value = ElementZ
for i := 1 to Atoms.Count-1 do // or AtomCount-1
// you have still direct access to AtomArray[]
// -> this is even the fastest access to the data
assert(AtomArray[i].ElementZ >=AtomArray[i-1].ElementZ )
Atoms.SaveToStream(aStream); // will also save any string content
Atoms.Reverse; // reverse all items order
Atoms.Clear;
// faster adding will be done with direct access to the dynamic array
Atom.Count := 10000; // allocate memory for 10000 items
for i := 0 to 10000-1 do
with AtomArray[i] do
begin
ElementZ := Random(2000);
X := Random;
Y := Random;
Z := Random;
end;
Atoms.Sort; // TDynArray knows about the data just created
end; // no need to have any try...finally ..Free block
适用于 Delphi 6 至 XE。
随着新版本的 Delphi 支持泛型,您最好朝这个方向发展。