Zitat von
scp:
aber die hier dargestellte TStrList unterscheidet sich kaum vom Original.
Aber das bisschen ist schon sehr ausschlaggebend.
Zitat:
Auch bei der Borlandschen Version wird ein array verwendet, nur ist dies halt eine andere Art dynamisches Array:
Das ist nicht das Problem.
Zitat:
5000 * 4 Byte sind doch 20000 Byte ~ 19,5 KB, oder wie meinst du das?
Theoretisch werden die 20000 Bytes auch nur reserviert. Praktisch wird Windows aber der Speicher in nicht geringen Mengen entzugen.
Zitat:
Es ist also zunächst eine statische Array, die aber nur den gerade nötigen Teil für die Anzahl Items per ReAllocMem() zugewiesen bekommt. Dies benötigt aber ebenfalls pro Element einen Integer-Wert (eigentlich ja Pointer), also 4 Byte + die Stringdaten.
Um es mal übertrieben darzustellen: Mit dieser Technik mishandelst du den Speichermanager von Delphi, der es dir dann mit einem Speicherbedraf gegen unendlich heimzahlt.
Bei jedem SetLength(a, Length(a) + 1) wird ein neuer Speicherbereich reserviert, die Daten kopiert und der alte als "Frei" vermerkt, also nicht an Windows zurückgegeben, da er später wieder benutzt werden könnte und somit schneller bereit steht, als wenn er erst bei Windows angefordert werden muss. Kommt nun die nächste Vergrößerung, so muss der Speichermanager wieder einen neuen Speicherbereich bei Windows reservieren, da das nun größere Array nicht in einen zuvor reservierten Speicher passt ...
Darum ist es besser, wenn man das Array einmalig auf die End-Länge setzt, anstatt jedesmal eins zur Länge hinzuzuaddieren. Man spart sich auch das ständige Kopieren des Arrays und gewinnt neben Speicherplatz auch an Geschwindigkeit.
Delphi-Quellcode:
var
i: Integer;
a: array of Integer;
begin
ShowMessage('Start - Speicherschlucken');
a := nil;
for i := 0 to 99999 do
begin
SetLength(a, Length(a) + 1);
a[i] := i;
end;
ShowMessage('Ende');
end;
Delphi-Quellcode:
var
i: Integer;
a: array of Integer;
begin
ShowMessage('Start - Schneller und Speicherschonend');
SetLength(a, 100000);
for i := 0 to 99999 do
a[i] := i;
ShowMessage('Ende');
end;