Diese .List Property ist ja schon immer™ der Zugriff auf das interne Array gewesen.
Auch schon bei der alten System.Classes.TList.
Nutze ich in der Regel auch in Schleifen, wenn von 0 bis Count - 1 iteriert wird, um die GetItem-Funktion zu umgehen.
Die mag zwar je nach Delphi-Version zwar inline markiert sein, aber es wird unnötig Index >= FCount geprüft.
Hat idR keinerlei Auswirkung auf die Performance - hier mal das Ergebnis von ner hingeschluderten Benchmark:
Code:
-------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------
RTL-getter/10 9,31 ns 9,28 ns 64000000
RTL-getter/100 114 ns 115 ns 6400000
RTL-getter/1000 1150 ns 1147 ns 640000
RTL-getter/10000 11550 ns 11475 ns 64000
RTL-getter/100000 115873 ns 117188 ns 5600
RTL-list/10 9,16 ns 9,21 ns 74666667
RTL-list/100 113 ns 115 ns 6400000
RTL-list/1000 1151 ns 1144 ns 560000
RTL-list/10000 11577 ns 11719 ns 64000
RTL-list/100000 115813 ns 117188 ns 6400
Sollte man übrigens runtime packages nutzen, fällt das inlining weg und der Zugriff auf .List wird nicht mehr geinlined und jedesmal aufgerufen, was diesen Ansatz ca 10mal langsamer macht, der nicht mehr geinlinete Getter hingegen kostet nur ca 50% mehr. Dieselbe Benchmark mit
rtl als runtime
package:
Code:
-------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------
RTL-getter/10 16,9 ns 16,9 ns 40727273
RTL-getter/100 169 ns 169 ns 4072727
RTL-getter/1000 1639 ns 1650 ns 407273
RTL-getter/10000 16257 ns 16392 ns 44800
RTL-getter/100000 163355 ns 161122 ns 4073
RTL-list/10 146 ns 146 ns 4480000
RTL-list/100 1461 ns 1475 ns 497778
RTL-list/1000 14593 ns 14300 ns 44800
RTL-list/10000 145201 ns 142997 ns 4480
RTL-list/100000 1452860 ns 1443273 ns 498
Benchmark Code:
Delphi-Quellcode:
uses
Spring.Benchmark,
Generics.Collections;
procedure RTLGetter(
const state: TState);
var
list: TList<Integer>;
count, i: Integer;
sum: Integer;
begin
list := TList<Integer>.Create;
count := state[0];
for i := 1
to count
do
list.Add(i);
sum := 0;
while state.KeepRunning
do
begin
sum := 0;
for i := 0
to list.Count - 1
do
Inc(sum, list[i]);
end;
state.Counters['
sum'] := sum;
list.Free;
end;
procedure RTLList(
const state: TState);
var
list: TList<Integer>;
count, i: Integer;
sum: Integer;
begin
list := TList<Integer>.Create;
count := state[0];
for i := 1
to count
do
list.Add(i);
sum := 0;
while state.KeepRunning
do
begin
sum := 0;
for i := 0
to list.Count - 1
do
Inc(sum, list.List[i]);
end;
state.Counters['
sum'] := sum;
list.Free;
end;
begin
Benchmark(RTLGetter, '
RTL-getter').RangeMultiplier(10).Range(10, 100000);
Benchmark(RTLList, '
RTL-list').RangeMultiplier(10).Range(10, 100000);
Benchmark_Main();
end.