![]() |
NonVCL Version von Classes.dcu
Gibt es eine NonVCL für die unit Classes, denn brauche TString aus dieser Unit, doch leider wird die Datei von 8,5KB 114KB groß, wenn ich Classes einbinde.
Kann mir vielleicht jemand helfen? :love: Danke UC |
Re: NonVCL Version von Classes.dcu
TString? Ich kenne nur TStrings. Wenn du eine Stringliste brauchst, dass kan man sich einfach mit einem dynamsischen Array of String selber als Klasse nachprogrammieren.
|
Re: NonVCL Version von Classes.dcu
:love: Danke, werde das mal probieren.
PS: Ich meinte auch TStrings :roll: |
Re: NonVCL Version von Classes.dcu
Auch eine schöne Fingerübung, um sich mal Klassen anzukucken. :zwinker:
|
Re: NonVCL Version von Classes.dcu
Ich bekomme das irgendwie nicht hin was zu ADDen :?
Ich wollte ![]() Es soll mir jetzt keiner die Funktion in NonVCL machen, denn dann versteh ich es nicht, mir soll nur ein bisschen geholfen werden wie man das macht. :love: Danke UC |
Re: NonVCL Version von Classes.dcu
|
Re: NonVCL Version von Classes.dcu
:love: Danke, ganau das habe ich gesucht. Ganz ohne Array ist immer noch besser :roll:
PS: Du musst in deiner Signatur noch was einfügen, denn nur die Countdownzahl sieht irgendwie komisch aus :zwinker: |
Re: NonVCL Version von Classes.dcu
Ich hab' das nochmal probiert, dass auf die Funktion umzustellen, doch irgendwie klappt das nicht :?
Man kann zwar die Datei kompilieren, doch wenn ich die Datei starte kommt ein Anwendungsfehler, gibt es vielleicht noch eine andere Variante? |
Re: NonVCL Version von Classes.dcu
Wo ist das Problem? Du nimmst dir ein dynamisches Array of String. Jedes mal, wenn du was hinzufügst (Methode Add) verlängerst du das Array um eins und fügst den String dort ein.
Delphi-Quellcode:
Nur mal so schnell ins Forum gehackt. Wenn es auch nicht kompiliert, sollte es zu mindest das Prinzip zeigen.
type TDynStringArray = array of Strings;
type TMyTringList = class private sl: TDynStringArray; public constructor Create; procedure Add; end; constructor TMyStringlist.Create; begin ...; end; procedure TMyStringList.Add(s: String); var len: Integer; begin len := length(sl); len := SetLength(sl, len+1); sl[len] := s; end; |
Re: NonVCL Version von Classes.dcu
Zitat:
Zitat:
|
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. |
Re: NonVCL Version von Classes.dcu
Zitat:
Schau einfach mal in der Classes.pas, hast ja die D6Pro. |
Re: NonVCL Version von Classes.dcu
Zitat:
Zitat:
Du kannst den folgenden Speichermanager, der nichts anderes macht als den Windows-Speichermanager aufzurufen, ja mal als Ersatz nehmen. (Erste Unit im Projektquellcode). Der Geschwindigkeitsunterschied bei vielen Komponenten auf den Formularen ist spürbar.
Delphi-Quellcode:
unit WinMemMan;
interface uses Windows; implementation const HEAP_NO_SERIALIZE = 1; HEAP_ZERO_MEMORY = 8; HeapFlags: array[False..True] of Cardinal = (HEAP_NO_SERIALIZE, 0); var ProcessHeap: THandle; function HeapGetMem(Size: Integer): Pointer; begin Result := HeapAlloc(ProcessHeap, HeapFlags[IsMultiThread], Size); end; function HeapFreeMem(P: Pointer): Integer; begin if HeapFree(ProcessHeap, HeapFlags[IsMultiThread], P) then Result := 0 else Result := 1; end; function HeapReallocMem(P: Pointer; Size: Integer): Pointer; begin Result := HeapReAlloc(ProcessHeap, HeapFlags[IsMultiThread], P, Cardinal(Size)); end; procedure InitializeHeapMemManager; var HeapMemManager: TMemoryManager; begin ProcessHeap := GetProcessHeap; HeapMemManager.GetMem := HeapGetMem; HeapMemManager.FreeMem := HeapFreeMem; HeapMemManager.ReallocMem := HeapReallocMem; SetMemoryManager(HeapMemManager); end; initialization InitializeHeapMemManager; end. |
Re: NonVCL Version von Classes.dcu
[quote="scp"]
Zitat:
Zitat:
|
Re: NonVCL Version von Classes.dcu
Stimmt, die kenn ich zwar, hatte sie aber jetzt völlig ausser acht gelassen. Na dann eine andere Theorie:
Ist es nicht möglich, das bei einem dynamischen Array intern die gleiche vorgehensweise wie bei TStringList verwendet wird? |
Re: NonVCL Version von Classes.dcu
Natürlich. Schau dir einfach mal an, wie Borland das bei TStringList/TList mit Capacity gelöst hat. Einfach mal die gesamte Classes.pas nach Capacity durchsuchen. Dort wirst du auch eine schöne Formel finden, die sehr effektiv ist.
Da TStringList/TList noch aus Delphi 1 Zeiten stammen, wo dynamischen Arrays noch nicht vom Compiler unterstützt wurden, hat Borland einfach die "alte Art" der dynamischen Arrays benutzt. |
Re: NonVCL Version von Classes.dcu
Ich selbst nutze sowieso mittlerweile die "alte Variante", da ich die Quelltexte auch auf D3 laufen haben will. Schliesslich kann sich das jetzt jeder leisten.
Aber interessant mal die doch gravierenden Unterschiede kennenzulernen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:47 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