Delphi-PRAXiS
Seite 2 von 7     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Maßnahmen zum Speicherverbrauch minimieren (https://www.delphipraxis.net/185886-massnahmen-zum-speicherverbrauch-minimieren.html)

Mavarik 15. Jul 2015 14:14

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Zitat:

Zitat von Union (Beitrag 1308753)
Zitat:

Zitat von Mavarik (Beitrag 1308752)
Zitat:

Zitat von hoika (Beitrag 1308744)
die Umstellung auf ShortString bringt wohl gar nichts, wird wohl eher größer:
ein String[50] mit "123" verbraucht mehr Speicher als ein String mit "123".

Wie kommst Du den da rauf?

Vielleicht weil es so ist?
Zitat:

Zitat von DokWiki
While the length of a ShortString can change dynamically, *its memory is a statically allocated 256 bytes*; the first byte stores the length of the string, and the remaining 255 bytes are available for characters


LOL

Daher ja STRING[5] oder was auch immer... Und der braucht auch nur 6 Byte

Union 15. Jul 2015 14:19

AW: Maßnahmen zum Speicherverbrauch minimieren
 
JEDER Shortstring wird mit 256 Byte alloziiert. BELEGT werden davon dann nur 6, das ist richtig. Eine sehr schöne Erläuterung findet sich hier oder in der offiziellen Dokumentation.

Mavarik 15. Jul 2015 14:38

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Zitat:

Zitat von Union (Beitrag 1308756)
JEDER Shortstring wird mit 256 Byte alloziiert. BELEGT werden davon dann nur 6, das ist richtig. Eine sehr schöne Erläuterung findet sich hier oder in der offiziellen Dokumentation.

Ja dann mal aus der offiziellen Docu:

Zitat:

Zitat von docwiki.embarcadero.com

Hier wird die Variable MyString mit einer maximalen Länge von 100 Zeichen erstellt. Dies entspricht den folgenden Deklarationen:
Delphi-Quellcode:
type CString = string[100];
var MyString: CString;
Bei Variablen, die auf diese Weise deklariert werden, wird dem Typ nur so viel Speicherplatz zugewiesen, wie für die angegebene Länge plus ein Byte erforderlich ist. In diesem Beispiel belegt MyString 101 Byte

Die Frage ist eigentlich wie oft sind die Strings mit welcher länge gefüllt...
Wenn ich einen String[80] definiere aber immer nur "ABC" rein schreibe ist das natürlich quatsch...
Dann ist der Ansistring besser... Aber spätestens wenn ich die AnsiStrings in einem Record habe, klappen schon keine Zuweisungen des Records mehr... keine Moves, keine Blockwrites... (Oder für die "neuen": kein Streamwrite in einem Rutsch)

Union 15. Jul 2015 14:46

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Mit dem Umweg über einen eigenen Typen geht es tatsächlich, da hast Du vollkommen Recht. Nur muss man dann für jede mögliche Maximallänge eine Typdefinition erstellen - um das gleiche Ergebnis zu erreichen wie mit einem (P)Ansistring. Ich denke, ein Lazy-Loading Pattern in Verbindung mit einem eigenen GC sollte mehr Erfolg versprechen.

stahli 15. Jul 2015 14:51

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Danke für Eure Hilfe!

Ich bin auch etwas überrascht, dass der Speicherbedarf so hoch ist.
Mit etwas einfacheren Objekten konnte ich 3-4 Mio Stück erzeugen.
Wenn allerdings jedes Objekt wieder n Unterobjekte verwaltet, dann reduziert das natürlich die Anzahl der Hauptobjekte.

Mit Unterobjekten sind dann sowohl die Verwaltungsobjekte gemeint, die Businessobjektreferenzen verwalten, als auch die benötigten untergeordneten Businessobjekte selbst.

Businessobjekte werden von einer Factory erzeugt und zentral verwaltet. Die Factory gibt dann nur Interfaces auf diese Objekte heraus.
Eine Objektinstanz wird nur neu erstellt, wenn es noch keine entsprechende gibt. Sonst wird das existierende Objekt wiederverwendet.

Memoryleaks habe ich nicht (bis auf 4 kleine Indy-Klassen - scheint wohl ein Bug zu sein, der aber jetzt hier nicht wirklich relevant ist).

Anbei mal ein Screenshot eines veralteten MemLogs. Die StringLists habe ich inzwischen schon entfernt. Das erhöhte die Objektanzahl schon mal von 70T auf knapp 100T.

Dass die RTTI-Entfernung nur eine einmalige Auswirkung hätte ist mir klar. Ich weiß nur nicht, wie viel das ausmacht und was es noch für Optionen gäbe.

Die Info mit dem ShortString ist hilfreich. So weit war ich noch nicht vorgedrungen. In der Hilfe sah es irgendwie so aus, als wären ShortString und WideString identisch.
AnsiString für die Namenbezeichner dürfte aber sicher was bringen, denke ich.

Ich werde also mal Stück für Stück schauen, was ich an meinen Klassen optimieren kann.
So einen richtigen Brüller, der hier mal schnell zu einer großen Entlastung führt, habt Ihr offenbar auch nicht zur Hand.

Dass mein Manager später den Speicherverbrauch überwachen und Objektdaten wegschreiben und die Objekte wieder auflösen muss ist klar.
Aber um so optimierter die Objekte verwaltet werden um so mehr können im Speicher gehalten werden und um so performanter kann das Ganze laufen.

Ich werde also mal die Details prüfen, wie String zu AnsiString oder Listenobjekte erst instanziieren, wenn ein Unterobjekt hinzugefügt werden soll etc...

Mavarik 15. Jul 2015 14:58

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Zitat:

Zitat von Mavarik (Beitrag 1308754)
Sagen wir mal Du nimmst dir 1GB RAM... Und willst da 200.000 Objecte unter bringen...
Dann kann jedes Object 5,2 MB groß sein...

Gelesen?

Kann es sein, dass Du dich mit deinen Zeigerliste ein wenig zu Tode verwaltest?

Wenn Du mal verrätst was Du speichern willst, können wir sicherlich besser helfen...

stahli 15. Jul 2015 15:09

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Das schaue ich mir jetzt mal an...

hstreicher 15. Jul 2015 16:15

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Zitat:

Zitat von Mavarik (Beitrag 1308754)
Sagen wir mal Du nimmst dir 1GB RAM... Und willst da 200.000 Objecte unter bringen...
Dann kann jedes Object 5,2 MB groß sein...


5,2 KB , sonst wirds 1 TB Ram

Dejan Vu 16. Jul 2015 06:42

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Zitat:

Zitat von hstreicher (Beitrag 1308767)
Zitat:

Zitat von Mavarik (Beitrag 1308754)
Sagen wir mal Du nimmst dir 1GB RAM... Und willst da 200.000 Objecte unter bringen...
Dann kann jedes Object 5,2 MB groß sein...


5,2 KB , sonst wirds 1 TB Ram

LOL

Wäre es nicht denkbar, das Klassen an sich mehr Speicherplatz verbraten, als z.B. Records?

Davon unabhängig solltest Du einfach mal messen, wie groß ein Businessobjekt inklusive aller Unterobjekte ist. Dazu kannst Du dir ja einfach eine Funktion 'Size' für alle Klassen implementieren:

Delphi-Quellcode:
Function TMyObject.Size : Integer;
begin
  Result := SizeOf(FMyDouble)+StringSize(FMyString);
  For item in FMyObjectList do
    inc(Result, item.Size);
end;
Dann hast Du schon einmal den Nettoverbrauch an Daten. Das solltest Du in der Factory machen, d.h. die Factory führt darüber Buch, wie viel Bytes es bisher produziert hat.

Wäre doch mal interessant, ob wirklich die Objekte das Problem sind, oder nicht etwas anderes.

Wie sehen deine Objekte denn in etwa aus? Müssen es Namen (String) sein, um ein Objekt zu identifizieren? Tut es ein integer nicht auch?

stahli 16. Jul 2015 09:10

AW: Maßnahmen zum Speicherverbrauch minimieren
 
Ich habe gestern einfach mal String durch AnsiString ersetzt.

Nach Studium der Hilfe http://docwiki.embarcadero.com/RADSt..._in_RAD_Studio
war zu erwarten, dass es nicht sehr viel ausmachen wird. Und so ist es auch.
Statt 92539 Hauptobjekten konnte ich 97059 erzeugen.

Wie bereits beschrieben, sind das die Hauptobjekte, denen diverse Eigenschaften, Listen und Referenzzeiger zugeordnet sind.
Wirkliche Objekte werden viel mehr erzeugt.

Auf die Namen kann ich nicht verzichten. Aber ich könnte einen platzsparendere Stringtyp wählen. Ich weiß nur noch nicht welchen.


Ich habe gestern mal versucht, mit AQTime Pro den Speicherbedarf einer Methode zu profilen, in der eines meiner Hauptobjekte erzeugt wird.
Im Gegensatz zu dem Performance-Profile ist das aber beim Allocation-Profiler scheinbar so nicht möglich. Zumindest habe ich das gestern nicht hingekriegt.
Also werde ich das mal (wie von Dejan Vu vorgeschlagen) von meiner Factory protokollieren lassen oder das Projekt entfrachten und nur ein Mainobject erzeugen und dieses mit AQTime analysieren.

Über eine schrittweises Debuggen ist mir erst mal nichts falsches aufgefallen. Es sind halt recht viele Untereigenschaften und ich werde schauen müssen, was ich dort optimieren kann.

Ich werde mich also mal weiter Stück für Stück voran tasten...


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:28 Uhr.
Seite 2 von 7     12 34     Letzte »    

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