AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Speicherverwaltung von Delphi (Compiler)
Thema durchsuchen
Ansicht
Themen-Optionen

Speicherverwaltung von Delphi (Compiler)

Ein Thema von Tonic1024 · begonnen am 5. Aug 2005 · letzter Beitrag vom 31. Aug 2005
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Tonic1024
Tonic1024

Registriert seit: 10. Sep 2003
Ort: Cuxhaven
559 Beiträge
 
RAD-Studio 2009 Ent
 
#1

Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 08:46
hallo community...

Es ist ja so, dass Delphi den Speicherbedarf bei Windows anmeldet und dann immer mehr Bröckchen dazubekommt. Ein mit Delphi compiliertes Programm sammelt sich also einen relativ großen Pool an Speicher zusammen. Das ist insofern ja auch sinnvoll weil der interne Speichermanager viel schneller arbeitet als ständig Speicher im OS anzumelden. Wenn das Programm beendet wird wird der Speicher wieder freigegeben. So Weit, so Gut.

Ich habe jetzt eine Art Dienst geschrieben, aber nur als normales Programm gestartet (Autostart), der auf einem Server (eigentlich ne normale 2k Workstation) läuft und mehrmals am Tag Textdateien automatisch in eine Datenbank einliesst. Dieses Programm braucht aber mit der Zeit unmengen an Speicher. Okay, 20MB sind nicht sooo viel, aber es ist auch nur ein kleines Programm. Und der Speicherbedarf wächst jeden Tag, den das Programm läuft.

Kann man das abstellen? Ich habe das schon bei mehreren Programmen beobachtet. Und eigentlich habe ich alle Variablen, die dafür verantwortlich sein könnten explizit wieder freigegeben. Darum denke ich, das zwar die Variable freigegeben wird, das oben angesprochene Speichermanagement aber den Speicher nicht an das OS zurück gibt. Kann man da was dran machen? Ich meine ausser eine Neustartautomatik nach 7 Tagen, oder so? Das wäre zwar sicherlich wirksam, fände ich aber keinen schönen Stil.

MfG

Toni
Der frühe Vogel fängt den Wurm, richtig.
Aber wird nicht auch der frühe Wurm vom Vogel gefressen?
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.195 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 08:57
Hast du mit Memcheck mal überprüft ob wirklich alles wieder freigegeben wird?
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#3

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 09:02
Schau dir mal http://sourceforge.net/projects/fastmm an.
Ein alternativer (und schnellerer) MemoryManager fuer Delphi.
Auf news://newsgroups.borland.com/borlan....language.basm laufen dazu die Diskussionen.

Ich bin nicht sicher ob man die Rueckgabe des freien Speichers an Windows veranlassen kann, aber wenn nicht, dann baut es der Autor gerne ein.
  Mit Zitat antworten Zitat
Benutzerbild von Tonic1024
Tonic1024

Registriert seit: 10. Sep 2003
Ort: Cuxhaven
559 Beiträge
 
RAD-Studio 2009 Ent
 
#4

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 10:04
So, ich habe mich zunächst zunächst in memcheck eingearbeitet, weiss allerdings nicht ob ich das Teil richtig bediene. Hab es so eingebunden wie in dem Tutorial beschrieben und bekomme die Meldung, dass 122 Bytes leaken. Da ich ja quasi ne Endlosschleife (nen Timer) benutze könnt ich mir vorstellen, dass die dafür verantwortlich sind, allerdings müsste das Programm kontinuierlich 10 Wochen laufen, damit es hinkommt. Das passt aber mit meinen Beobachtungen nicht überein. (Kann man das überhaupt so rechnen? - egal)

Ich habe auch quasi meinen kompletten Quellcode auskommentiert und immernoch 86 byte leak. Bin mir nicht sicher wie ich die Textdatei lesen muss...
Zitat von MemChk:
Leak #0 User allocated memory (GetMem)
Size: 106
1 Occurence
call stack - 0 : Routine @Sysutils@Exception@CreateFmt Find error: 0040C3B9
call stack - 1 : Routine @Sysutils@Exception@CreateFmt Find error: 0040C3B5
call stack - 2 : Routine CreateAVObject Find error: 0040C880
call stack - 3 : (no debug info) Find error: 0040C979
call stack - 4 : Routine @System@@ExceptionHandler Find error: 004044D2
call stack - 5 : (no debug info) Find error: 77896C3E
call stack - 6 : (no debug info) Find error: 7789FF6A

Leak #1 User allocated memory (GetMem)
Size: 16
1 Occurence
call stack - 0 : (no debug info) Find error: 0012F704
call stack - 1 : (no debug info) Find error: 0040C979
call stack - 2 : Routine @System@@ExceptionHandler Find error: 004044D2
call stack - 3 : (no debug info) Find error: 77896C3E
call stack - 4 : (no debug info) Find error: 7789FF6A
Werd mich jetzt mal mit dem Speichermanager beschäftigen. Aber generell bin ich gegen solche Anpassungen in Delphi. Nicht weil sie vielleicht nicht sinnvoll sind, sondern weil dann jemand anderes, der Standard-Delphi hat oft solche Projekte nicht mehr kompilieren kann. Werd jedenfalls mal testen.

Toni

[Edit]Interessannt: Ein völlig anderes Projekt, dass ebenfalls 24/7 läuft (ein Unsinn/Spaß-Prog), hat quasi 1:1 die selben Resultate gebracht [/Edit]
Der frühe Vogel fängt den Wurm, richtig.
Aber wird nicht auch der frühe Wurm vom Vogel gefressen?
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#5

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 10:15
Nachdem Wirbel und den überzeugenden Benchmarks in der BASM NG würde ich eher die Frage in den Raum werfen: Warum sollte man für einen Dienst nicht den FastMM oder den NexusMM nehmen?
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.195 Beiträge
 
Delphi 10.4 Sydney
 
#6

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 10:25
Zitat von Tonic1024:
Ich habe auch quasi meinen kompletten Quellcode auskommentiert und immernoch 86 byte leak. Bin mir nicht sicher wie ich die Textdatei lesen muss...
Kompiliere deine Exe mal mit TD32-Debug-Infos und Debug-DCU's.
Dann bekommst du lesbarere Informationen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Tonic1024
Tonic1024

Registriert seit: 10. Sep 2003
Ort: Cuxhaven
559 Beiträge
 
RAD-Studio 2009 Ent
 
#7

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 5. Aug 2005, 10:38
Jap, hab ich bereits gemacht, wie in der Anleitung beschrieben steht. Alles was ich da rauslesen kann ist, dass das in den sysutils passiert... Das passiert im Exceptionhandling und scheint für mich alles Interna zu sein. Nichts was mich auf den Ursprung schließen lässt.

Werd nochmal recherchieren was genau das sein könnte...
Der frühe Vogel fängt den Wurm, richtig.
Aber wird nicht auch der frühe Wurm vom Vogel gefressen?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#8

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 29. Aug 2005, 11:37
Ich sag lieber auch mal was zu diesem Thema, auch wenn's mittler Weile schon 'n bissl spät ist.

Also erstmal dazu, warum ich hier vermutlich mitreden kann:
Und zwar hatte ich auch vor 'ner "ganzen" Weile mal ein derartiges Problem, dabei wurden in einem Programm abundzu einige tausende Strings (also viele - derzeit nur etwas über 20.000 - nette kleine und auch größere Speicherblöcke) erstellt, diese wurden dann überarbeitet und dabei auch öfters mal in der Größe verändert.

Nun sei ja zu beachten, dass die "meißten" von Programmen erstellten Speicherblöcke statisch sind, also nicht verschoben werden können.
Wenn jetzt öfters Speicherplatz reserviert und freigegeben wird, dann entstehen zwischen diesen Blöcken viele Lücken, welche unter umständen nicht mehr genutzt werden können, weil sie z.B. zu klein sind.
Dazu kommen dann noch die ungenutzen Blockanteile, welche durch die Sektorisierung des speichers entstehen ... denn normaler Weise werden die einzelnen Blöcke ja an bestimmten Grenzen ausgerichtet ... wenn jetzt also eine bestimmte Menge an Speicher bestellt wird, dann reservieren die verschiedenen Speichermanager (z.B. die von Delphi und Windows) ja einen kompletten Block und das Blockende bleibt ungenutzt.

Auch zu beachten sein, dass Delphi's Memory Manager und auch die meißten Anderen sich "größere" Speicherblöcke von Windows holen und diese dann intern in "kleineren" Teilen an die verschiedenen Variablen weitervermieten, aber diese Blöcke können natürlich nur wieder an Windows zurückgegeben, wenn auch der geamte Block wieder frei ist ... sollte also auch nur eine winzige Variable noch darin rumrliegen, bleibt der entsprechende Block beim Programm.
Wenn man sich also massig Speicher reserviert und dafür sorgt, das in jedem Block auch nur ein Byte belegt bleibt, nachdem man den größten Teil wieder freigegeben hat, dann muß das Programm diese Blöcke ja behalten, auch wenn die vielen Einzelbytes mit Sicherheit in nur einen einzigen kleinen Block reinpassen würden.

Nun können sich diese nicht nutzbaren Speicherbereiche sogar noch ansammeln ... sowohl über die Anzahl der reservieren Blöcke und natürlich auch durch die ständigen Reservierungen/Freigaben.
Bei mir zeigte sich dieses Verhalten darin, dass anstatt nur effektiv etwa 20 bis 60 MB der tatsächliche Verbrauch auf über 200 MB anstieg und nach einer Weile dann auch mal auf über 700 MB ausweitete, (irgendwann kamm halt dann das "out of memory")
obwohl die Datenmenge im Speicher eigentlich gleich blieb ... die Daten wurden bei mir ja nur zwischen den Strings verschoben und manchmal wurde sogar einer gelöscht, also müßte der Speiche ja eigentlich kleiner und nicht größer werden.

Zuerst dachte ich ja auch an ein Speicherleck und hab Tage lang nach diesem Leck gesucht ... allerdings konnte ich zu meiner Frustration nichts finden ... bis ich dann letztendlich auf dieses Verhalten stieß.

Natürlich könnte man ja auch TStrings und seine Kinder für die Verwaltung vieler Strings verwenden, da dieses nur einen "großen" Speicherbock verwendet und die Strings hinereinandergereiht darin ablegt.
Allerdings ist TStrings und Co. nicht gerade schnell, wenn es um große Datenmengen geht, da ja unter Umständen ein großer Anteil der Daten darin verschoben werden muß, wenn man z.B. in einem der Einzelstrings auch nur ein einziges Zeichen einfügt/löscht, warum ich ja auch auf Einzelne Strings umgestiegen bin ... der enorme Geschwingigkeitszuwachs von teilweise bis zu 3.000% hatte mich zuerst überzeugt und ich konnte/wollte nicht mehr zu TStrings zurück.


Im Endefekt konnte ich es dann nur über eine selbst programmierte Speicherdefragmentierung lösen, welche sich jetzt in "regelmäßigen" Abständen über den Speicher meiner Anwendung hermacht.

Allerdings gibt es für eine Defragmentierung gewisse Einschränkungen.
  • entweder man verwendet von Anfang an dynamische Speicherblöcke
    z.B. indem man den Delphi-Speichermanager umgeht und per GlobalAlloc mit GMEM_MOVEABLE dynamische Blöcke reserviert,
    denn solange der Block UNLOCKED und ohne Zugriff ist, kann windows diesen Block ja beliebig verschieben (mit GlobalLock bekommt man dann an den aktuellen Pointer auf diesen Block)
  • oder man muß bei der Definierung der relevanten Variablen dafür sorgen, dass man selber eine Defragmentierung vornehmen und die Pointer entsprechend anpassen kann.



Wenn man sich über die Speicherverteilung seiner Anwendung informieren will, um z.B. eine derartiger Defragmentierung besser zu erkennen, kann man sich auch einen Speichermanager wie FastMM einbauen und den zugehörigen "Usage Tracker" verwenden.



Ich hab mal meinen kleinen eigenen "FastXMM Usage Tracker" als Demo angehängt.
Dieser basiert auf dem FastMM 4.26 von Pierre le Riche.
Allerdings hab ich seinen Memory Manager sehr stark abgespeckt und mit zum Schluß mit einigen Teilen meines alten Memory Managers aufgerüstet.
Als die größten sichtbaren Veränderungen seien genannt:
  • die jetzt funktionierende Anzeige der von FastXMM reservierten Blöcke
    (Blockanteile werden aus Performancegründen Prozentual auf den Gesammtblock verteilt)
  • eine für die Speicherverwaltung optimalere Verteilung der SmallBlocks
  • die Unterscheidung von "normalem" Speicher und File-Images
    (z.B. ist das Grüne ganz oben die eigene EXE)
    und wenn man jetzt mit der Maus mal darüber geht, dann sollte (wenn möglich) unten rechts, bei der Adressanzeige, der Modulname auftauchen


Aber bevor jetzt Fragen kommen ... der Speichermanager steckt in meinem UCC drin und seit Kurzem hab'sch davon auch 'ne Single-Unit-Version (ohne UCC).
Diese scheint jetzt auch zu funkionieren, allerdings muß ich die Units noch 'n bissl aufräumen. (beim nächsten Besuch werd'sch diese dann wohl mitbringen)
Na ja, ich FastMM auch erst durch diesen Beitrag entdeckt und das ist ja auch noch nicht so lange her.





So, das hab ich jetzt mal gebraucht ... komm ja in letzter Zeit nicht so oft zum Schreiben ^^
Angehängte Dateien
Dateityp: exe usagetrackerdemo_516.exe (472,5 KB, 21x aufgerufen)
Dateityp: exe mmusagetrackerdemo_947.exe (479,5 KB, 28x aufgerufen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#9

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 29. Aug 2005, 13:21
[quote="himitsu"]Allerdings ist TStrings und Co. nicht gerade schnell, wenn es um große Datenmengen geht, da ja unter Umständen ein großer Anteil der Daten darin verschoben werden muß[quote]
Nur die 8*Anzahl Bytes der "Strings-Objects" Records müssen verschoben werden. Nicht die gesamten Stringdaten.

Zitat:
wenn man z.B. in einem der Einzelstrings auch nur ein einziges Zeichen einfügt/löscht
Da muss viel weniger verschoben werden, als wenn man einen gesamten String hat, da die Zeile viel kürzer ist. Wenn man aber auf die Text-Eigenschaft zugreift, dann wird das sehr langsam, weil TStringList dann alle Zeilen bei jeden Aufruf zu einem einzigen String zusammensetzt.
Deswegen sollte man die Text-Eigenschaft bei vielen Zeilen nicht so oft aufrufen. Sie optimiert zwar auch, da sie zuerst die Resultat-Länge ermittelt, den Speicher reserviert und dann die Zeilen mittels Move einfügt, aber das dauert eben auch seine Zeit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#10

Re: Speicherverwaltung von Delphi (Compiler)

  Alt 30. Aug 2005, 17:52
Hab in TStrings... noch nicht so genau reingeschaut.
Aber wenn wirklich nur so wenig drin verschoben/geändert wird, dann frag ich mich allerdings, warum es bei größerwerdender Datenmenge immer so extrem lange rumeiert?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz