![]() |
Re: NonVCL Version von Classes.dcu
Folgender Erweiterungsvorschlag für TStrList:
1. Die Funktion Strings in GetStr und Replace in SetStr umbenennen. 2. Die beiden Functionen in den protected Bereich verschieben. 3. Folgende Zeile ans Ende der public-Deklarition einfügen:
Delphi-Quellcode:
Somit hat man mit ein bißchen Code ein Stück mehr das Verhalten von TStringList / TStrings.
property Strings[Index : Integer] : String read GetStr write SetStr; default;
|
Re: NonVCL Version von Classes.dcu
Da sind aber viele Fehler drin in dieser Klasse TStrList ... :gruebel:
|
Re: NonVCL Version von Classes.dcu
Zitat:
|
Re: NonVCL Version von Classes.dcu
Zitat:
|
Re: NonVCL Version von Classes.dcu
Zitat:
|
Re: NonVCL Version von Classes.dcu
War ja auch nur die einfache Version. Dass dies Speichertechnisch eigentlich Selbstmord ist, hätte ich noch erwähnen sollen. Aber in der hier geposteten Unit wird es nicht anders gemacht.
|
Re: NonVCL Version von Classes.dcu
Zitat:
Auch bei der Borlandschen Version wird ein array verwendet, nur ist dies halt eine andere Art dynamisches Array:
Delphi-Quellcode:
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.
PStringItemList = ^TStringItemList;
TStringItemList = array[0..MaxListSize] of TStringItem; PS: 5000 * 4 Byte sind doch 20000 Byte ~ 19,5 KB, oder wie meinst du das? |
Re: NonVCL Version von Classes.dcu
Bei jedem Aufruf von SetLength wird das ganze Array an eine andere Speicherstelle verschoben, da nicht sicher ist, ob hinter der aktuellen Stelle noch genügend Platz dafür ist.
Durch irgendeine Schwäche im Delphi-Speichermanager (genaueres weiß ich auch nicht, würde mich auch mal interessieren) kann es nun passieren (und es passiert), dass der Speicher, den das Array vor dem Verschieben belegte, nicht wieder frei gegeben wird. Dadurch kommt die hohe Speicherbelastung zu Stande. Daneben ist es natürlich auch höchst in effizient, wenn ständig Massen von Daten rumgeschoben werden, nur weil ein neuer String dazukommz. |
Re: NonVCL Version von Classes.dcu
Zitat:
Zitat:
Zitat:
Zitat:
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; |
Re: NonVCL Version von Classes.dcu
@chewie
Ersteres kann ich ja verstehen, wenn dem so ist, ist das natürlich ineffizient. Aber das Massen von Daten verschoben werden, finde ich nicht so schlimm, es sind hier ja bei dem Bespiel mit den 5000 Elementen nur die 20 KB, was ja heutzutage nicht viel ist, die Daten der Strings bleiben ja unangetastet, weil es ja für jeden String einen Extra-Pointer/-Referenzzähler gibt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz