Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Wie kann man ein "halbes" Memory-Leak finden? (https://www.delphipraxis.net/114634-wie-kann-man-ein-halbes-memory-leak-finden.html)

Phoenix 28. Mai 2008 15:16


Wie kann man ein "halbes" Memory-Leak finden?
 
Hi,

ja, der Titel sagt es schon aus: Ich suche ein Memory-Leak, das nur halb eines ist.

Das Problem: Läuft die Anwendung, wächst der Speicher mit der Zeit ins Uferlose. Schliesse ich die Anwendung wird aber z.B. laut Eureka-Log der Speicher wieder vollständig freigegeben.

Ergo: Der gesamte angeforderte Speicher wird beim Beenden der Anwendung auch wieder freigegeben, irgendwo fragt die Anwendung allerdings mehr oder weniger regel- bzw. unregelmässig nach Speicher an und behält diesen, obwohl ich mir ziemlich sicher bin, dass sie diesen Speicher eigentlich schon viel Früher wieder freigeben könnte / müsste.

Das wäre an und für sich kein Problem, würde die Anwendung nur 8 Stunden am Tag genutzt dann beendet / am nächsten Tag neu gestartet. Blöderweise läuft diese Anwendung aber zumindest theoretisch 24/7/52. In der Praxis kachelt sie aufgrund mangels Speicher irgendwann ab.

Wie kann ich also so ein 'halbes' Speicherloch gezielt finden?

Ich hab echt keine Idee ausser den _gesamten_ Source durchzusehen, und an _jeder_ Stelle wo Speicher angefordert und freigegeben wird eine Ausgabe zu loggen. Nur ist der gesamte Source verdammt groß und das würde Ewigkeiten dauern. Gibts da einen besseren Ansatz?

tomsel 28. Mai 2008 15:22

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Hast du es schon mal mit MemProof o.Ä. versucht?

Bernhard Geyer 28. Mai 2008 15:22

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Ich vermute mal das du hier eine Komponenten so erzeugst das der Parent für die Freigabe verantwortlich ist.
Und anstatt das schon die vorhandene Instanz verwendet wird, wird jedesmal eine neue erzeugt.

Dax 28. Mai 2008 15:23

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von Phoenix
Nur ist der gesamte Source verdammt groß und das würde Ewigkeiten dauern. Gibts da einen besseren Ansatz?

Jup, einen Proxy-MM. Du bastelst dir einen eigenen Memory Manager, der nichts weiter tut, als Re-/De-/Allokationen zu loggen und dann alle Aufrufparameter an den ursprünglichen MM weiterzureichen.

Phoenix 28. Mai 2008 15:24

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von tomsel
Hast du es schon mal mit MemProof o.Ä. versucht?

Zitat:

Zitat von Phoenix
Schliesse ich die Anwendung wird aber z.B. laut Eureka-Log der Speicher wieder vollständig freigegeben.


Phoenix 28. Mai 2008 15:29

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von Dax
Jup, einen Proxy-MM. Du bastelst dir einen eigenen Memory Manager, der nichts weiter tut, als Re-/De-/Allokationen zu loggen und dann alle Aufrufparameter an den ursprünglichen MM weiterzureichen.

Im Prinzip also genau das, was Eureka-Log schon tut. Der matcht die halt am Ende gegeneinander und gibt das nicht aus.

Hast Du irgendwie einen Ansatz, was für ein Aufwand das wäre sowas zu schreiben? Insbesondere wenn man (wie ich) keinen Plan davon hat wie man sich in das Memory-Management einhängt?

Edit: Verklickt...

Sherlock 28. Mai 2008 15:30

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Es ist kein Memory-Management Problem...so wie ich das verstehe, sondern ein algorithmisches. Da werden Objekte erzeugt, die ja am Ende korrekt freigegeben werden. Nur werden die Objekte eigentlich nicht benötigt. Oder vielleicht nur kurzfristig, und werden viel zu spät freigegeben.

sherlock

DMW 28. Mai 2008 15:31

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Man munkelt, FastMM könne so etwas.

Phoenix 28. Mai 2008 15:32

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von Sherlock
Es ist kein Memory-Management Problem...so wie ich das verstehe, sondern ein algorithmisches. Da werden Objekte erzeugt, die ja am Ende korrekt freigegeben werden. Nur werden die Objekte eigentlich nicht benötigt. Oder vielleicht nur kurzfristig, und werden viel zu spät freigegeben.

Genau das habe ich ja in meinem OP vermutet.

Nur: Wie findet man diesen Fehler?

Sherlock 28. Mai 2008 15:34

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Algorithmisches findet man eigentlich nur durch Analyse der Algorithmen. Das bedeutet je nach vorhandenener Dokumentation schlimmstenfalls ein Codewalkthrough :(

Sherlock

Phoenix 28. Mai 2008 15:36

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Genau das wollte ich eigentlich nicht lesen :pale:

Sherlock 28. Mai 2008 15:37

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Ich habe aber bestimmt unrecht :) Ist fast immer so, vor allem wenn ich mir absolut sicher bin, daß ich recht habe ;)

Sherlock

alzaimar 28. Mai 2008 15:59

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Ich mache z.B. Folgendes:
1. Jedes Objekt einer Klasse bekommt eine bestimmte ID (Zähler), die ID ist ein privates Feld.
2. Ich schreibe die ID in eine TList (oder das Objekt selbst, egal).
3. Im Destruktur entferne ich das Object/ID wieder aus dieser Liste.
4. Im IOnitikalization-Abschnitt der Unit wird die Liste instantiiert
5. Im Finalization-Abschnitt schaue ich nach, ob die Liste leer ist....
6. Wenn die Liste nicht leer ist, dann ....
7. Nehme ich mir die erste ID, die nicht freigegeben wurde und ...
8. Setze nun im Konstruktor einen Breakpoint mit der Bedingung (ID=12345, 12345=ID des nicht freigegeben Objektes)
9. Nun warte ich, bis dieses Objekt erzeugt wird und kann im Stack nachschauen, wieso ich so blöd war, und dieses Objekt nicht freigegeben habe.
10. Das Das mache ich bis die Liste leer ist. FERTIG.

So, damit Du das aber nicht für jede Klasse machen musst, patchst Du einfach die Classes.Pas (da ist doch TObject drin, oder?) und bohrst kurz mal TObjects.Create und TObjects.Destroy auf.

shmia 28. Mai 2008 16:41

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Das scheint mir eher ein Speicher Fragmentierungsproblem zu sein.
Die Anwendung fragt beim Memory Manager nach Speicher in mehr oder weniger kleinen Blöcken.
Der Memory Manager holt sich den Speicher in grossen Blöcken (~ 1 MByte) mit VirtualAlloc() bei Windows
und verwaltet diese dann, indem er kleinere Blöcke der Anwendung zuteilt.

Angenommen, du hast folgenden Code:
Delphi-Quellcode:
for i := 1 to 1000 do
   astring := astring +'*';
dann wird der String immer länger und benötigt immer mehr Speicher.
Es wird immer wieder neuer Speicher angefordert und es bleiben jede Menge unbenützte Speicherblöckchen zurück.
Ein intelligenter Memory-Manager könnte die kleinen Blöckchen zu einem grossen Block zusammenfassen (Stichwort: Garbage collection ).
Der Delphi MM ist nicht so schlau und gibt Blöcke, die er in kleine Häpchen aufgeteilt hat nicht mehr an Windows zurück.

Man sollete also:
* Objekte in umgekehrter Reihenfolge freigeben als wie man sie erzeugt hat
* AnsiStrings und dynamische Arrays nicht Elementweise vergrössern
* statt dynamische Arrays, die häufig in der Grösse verändert werden die Klasse TList und deren Nachkommen verwenden.

Delphi-Quellcode:
// das wäre ein Beispiel, wie man es nicht machen sollte
SetLength(dynamic_array, Length(dynamic_array)+1);

himitsu 28. Mai 2008 22:31

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Und sicher, daß dieses MML im Memorymanager liegt?

Wenn ich z.B. am Memorymanager vorbei direkt bei Windows Speicher anfordere, dann gibt es nette Nebenwirkungen.

Viele MML-Test schlagen dann fehl, da sie vorzugsweise nur den Memorymanager überwachen, aber z.B. nicht VirtualAlloc ... wobei dann zwar ein MML vorhanden sein kann, aber es nicht erkannt wird.


Und dann gibt es noch das Problem der Speicherdefragmentierung ... da hat der Memorymanager dann viel Speicher zur Verwaltung angefordert, aber es wird nur ein Teil vom Programm verwendet ... der Rest liegt ungenutzt rum, was aber laut Definition kein Speicherleak ist.

Dax 28. Mai 2008 23:11

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von Phoenix
Hast Du irgendwie einen Ansatz, was für ein Aufwand das wäre sowas zu schreiben? Insbesondere wenn man (wie ich) keinen Plan davon hat wie man sich in das Memory-Management einhängt?

Nein, leider nicht. Allerdings sollte in der Hilfe etwas zu TMemoryManager (oder so ähnlich) stehen - das Ding ist ein Record mit mehreren Funktionszeigern, die Delphi intern für GetMem, FreeMem usw verwendet.

himitsu 29. Mai 2008 00:48

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
und um eigene Funktionen zu setzen:

- mit Delphi-Referenz durchsuchenGetMemoryManager die aktuellen Adressen auslesen und speichern
- mit Delphi-Referenz durchsuchenSetMemoryManager die eigenen Funktionen übergeben

und in den eigenen Funktionen dann irgendwas machen und die Aufrufe an die alten (gespeicherten) Funktionen übergeben.

hewy 29. Mai 2008 07:50

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Hallo
Benutze doch mal FastMM. Kostet nichts und bringt dich ganz sicher weiter.
Dann poste den Log, und ich sage dir in welcher Zeile was aloziert wird das nicht wieder freigegeben wird.

Und so geht es:
In Datei FastMM4Options.inc von FastMM folgende Flags setzen:
{$define CheckHeapForCorruption}
{$define ClearLogFileOnStartup}
{$define EnableMemoryLeakReporting}

Im Delphi: in der dpr deiner Applikation.
program MeinProgramm;


uses
// >>>>>> Dies muss hier an erster stelle stehen
FastMM4,
idGlobal, IdThreadSafe, // for FastMM: registering expected leaks

Forms,
SysUtils,
Windows,
Classes,
Registry,



Im Delphi die Option vom Linker Include TD32 debug Info setzen und vollständig kompilieren. Die Applikation in der Delphi Umgebung betreiben, ein bischen überal hinklicken. Beim beenden wird eine Log Datei geschrieben.

Übrigens Memory leaks gibt es keine halben. In deinem falle handelt es sich ebenfalls um ein ganzes.

Phoenix 29. Mai 2008 07:51

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von shmia
Das scheint mir eher ein Speicher Fragmentierungsproblem zu sein.
[...]
Man sollete also:
[..]
* AnsiStrings und dynamische Arrays nicht Elementweise vergrössern
* statt dynamische Arrays, die häufig in der Grösse verändert werden die Klasse TList und deren Nachkommen verwenden.

Delphi-Quellcode:
// das wäre ein Beispiel, wie man es nicht machen sollte
SetLength(dynamic_array, Length(dynamic_array)+1);

Oha. :-(
Davon wird (in diesem Fall leider) an manchen Stellen exzessiver Gebrauch gemacht.

Also sollte ich vielleicht erstmal hier auf TList umstellen... Puuh.. das wird viel Arbeit.

Edit Nachtrag:
Nochmal @Hewy: Es gibt kein Leak. Alle Objekte, die irgendwann mal allokiert werden, werden auch wieder Freigegeben.
Blöderweise halt erst beim Beenden der Anwendung und nicht schon dann, wenn sie einfach nicht mehr benötigt werden.

Ergo: Es wird alles aufgeräumt. Sämtliche Tools wie FastMM & Eurekalog können kein Leak entdecken, weil eben im technischen Sinne keines existiert. Und ich denke nicht, dass FastMM meinen Code analysiert und mir aufzeigt, wo ich ein Objekt optimalerweise freigeben müsste, damit das nicht unnötig rumliegt.

Man.. ich würd mir so sehr eine Garbage-Collection wünschen.

Edit Nachtrag 2:

Würde sich das Fragmentierungs-Problem mit dem FastMM lösen?

alzaimar 29. Mai 2008 09:20

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von Phoenix
Würde sich das Fragmentierungs-Problem mit dem FastMM lösen?

Ein wenig. Verwendest Du COM? Ich hatte einmal mit einer komplexen COM-Library ähnliche Probleme und sie nicht in den Griff bekommen.

[klugscheiss]
Du kannst Deine dynamischen Arrays ruhig behalten, aber hier sieht man mal wieder, wie gut ordendliche OOP ist: So ein Array gehört gekapselt, damit man logische Operationen ('Einfügen eines Datensatzes mit eventueller Vergrößerung des Speichers') zentral implementieren kann. Dann hättest du einfach die Strategie des Speichervergrößerns ändern können. So musst du leider durch Deinen gesamten Code.
[/klugscheiss]
Das nicht als Verarsche für Dich, sondern als Beispiel, wieso OOP und Zentralisierung so wichtig ist.

DGL-luke 29. Mai 2008 09:32

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
schon lange nicht mehr delphifoniert, mal sehn ob ich meine ad hoc array-allokationsverwaltung noch zusammenkrieg:

Delphi-Quellcode:
var firstfree: integer;
    array: array of Typ;

function ArrayAdd(val: Typ): TResult;
begin
  if high(Array) < firstfree then
    setlength(array, length(array) * 162 div 100); //1.62 = magic number; feintunen sorgt evtl. für bessere performance je nachdem wie das array wachsen soll

  array[firstfree] := val;
  Inc(firstfree);
end;
is jetzt aus dem stegreif getippt und sicher auch algorithmisch nicht optimal. sollte speicherfragmentation aber vorbeugen, denn das array wird immer um einen bestimmten faktor vergrößert, d.h. je größer es wird, desto seltener muss es vergrößert werden.

TList ist aber evtl. wirklich sinnvoller! (wobei ich da nicht weiß wie optimal der array da drin behandelt wird)

Phoenix 29. Mai 2008 09:34

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Nein, ich benutze kein Com (zum Glück).

@Kapselung: Die Arrays sind gekapselt.
Ich dachte, das wäre Performancetechnisch ein Vorteil, meine Datenstrukturen in dynamischen Arrays zu verwalten, damit ich nicht den Overhead der Objektverwaltung habe an der Stele. Insbesondere wenn viel darauf gearbeitet wird.

Von daher ist das Umstellen auf TList / TObjectList auch nicht so der Riesen aufwand. Ich muss halt das array of in eine TObjectList ändern und die drei Methoden (reinpacken, rausholen, löschen) anpassen. Das halt in einigen klassen, aber so wild ist das nicht.

Aber wenn FastMM an der Stelle die Fragmentierung schonmal von sich aus zumindest eindämmen könnte, dann würde ich erstmal an deren Stellen suchen und ein Tracing für meine Datenbäume einbauen um zu sehen, wann ich da genau was drin habe und wann sich was ändert.

generic 29. Mai 2008 09:34

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Nutzt du Handels direkt?
(Filehandles, Fensterhandels usw.)

Phoenix 29. Mai 2008 09:42

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Nein, das sind keine Ressourcen. Das sind 'nur' ein haufen Objekte die ne Handvoll Daten bereitstellen, die ich in einer Art Tree verwalten muss, um da mittels Pointer-Operationen möglichst schnell drauf zugreifen zu können.

Das können halt schnell ein paar zigtausend Objekte werden, auf die ich im Worst-Case verdammt schnell zugreifen können muss. Und wenn sich an der Datenquelle was ändert, dann ändert sich halt auch ggf. der Aufbau des Trees. Und ich befürchte fast, dass ich in so einem Fall einfach irgendwo vergesse, alte, nicht mehr benötigte Objekte aufzuräumen. Die bleiben halt einfach in dem Tree hängen, aber auf diese Äste wird nie mehr zugegriffen. Am Ende wird logischerweise der ganze Baum aufgeräumt, deswegen bleiben diese Objekte auch ned liegen.

DGL-luke 29. Mai 2008 10:11

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
na dann lass doch mal das großreinemachen am ende weg. da wird dir das zeug schon ordentlich um die ohren fliegen :) und alle MMs mit leak-reporting (FastMM ist da echt gut!) werden dir zeigen, welche objekte da noch rumlunger,n evtl. sogar mit Klassenname und speicherbereich und zeilennummern, wo die objekte erzeugt wurden :)

EDIT: du kannst das natürlich auch selber machen. in die basisklasse deiner objekte (du hast sowas hoffentlich?) ein field lineofcreation: integer rein, Strg+F, ".Create", und überall zuweisen bei erstellung, und am ende alles was noch im tree hockt durchiterieren und schreien lassen.

Phoenix 29. Mai 2008 10:14

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von DGL-luke
na dann lass doch mal das großreinemachen am ende weg.

Dann hab ich tausende Objekte da drin, von denen ich weiss dass ich sie erst am Ende aufräumen muss.

Bei den tausenden dann ggf. genau die zig Objekte zu finden, die da nicht reingehören... das ist leider Utopisch.

DGL-luke 29. Mai 2008 10:16

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
gut, dann siehe mein edit, und zusätzlich noch ein bool "lazyObject" dazu (faul=liegt bis zum ende rum ;-))

EDIT: evtl. sogar als class const...

Phoenix 29. Mai 2008 10:24

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Ich hab einige zigtausende Objekte, die ich definitiv bis zum Ende brauche. Da ist nix Lazy.
Zudem ergibt sich das Problem nur dann, wenn die Anwendung eine ganze Zeit lang läuft. Deswegen kann ich auch nicht kurz Anwendung starten, hier und da rumklicken und dann beenden. Ich muss die mit Live-Daten etliche Stunden / Tage laufen lassen damit das Phänomen überhaupt auftritt.

Ob da wirklich Objekte drin sind, die ich vergesse aufzuräumen ist zudem nur Vermutung. Es könnte auch tatsächlich 'nur' an Fragmentierung liegen. Es kann allerdings genausogut an einer anderen Stelle im Programm liegen, deren Verantwortliche das aber kategorisch ablehnen.

Die Idee ist nun, mit möglichst wenig Aufwand (und ohne Try & Error) herauszufinden, ob das an meinem Teil liegt oder nicht. Insbesondere, weil wir das eben hier nicht auf die schnelle reproduzieren können.

alzaimar 29. Mai 2008 10:27

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von Phoenix
Und ich befürchte fast, dass ich in so einem Fall einfach irgendwo vergesse, alte, nicht mehr benötigte Objekte aufzuräumen.

Dann schreib dir eine Scanroutine, die nach einem Datenwechsel (wenn der Baum also aufgeräumt wird) nachschaut, ob auch wirklich alle Objekte weg sind. Dazu kannst du auch meinen Trick mit den IDs und der Liste nehmen. Einfach mitloggen, was erzeugt wird und hinterher durchgehen, welche Objekte gemeinerweise nicht freigegeben wurden...

Phoenix 29. Mai 2008 10:30

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von alzaimar
Dann schreib dir eine Scanroutine, die nach einem Datenwechsel (wenn der Baum also aufgeräumt wird) nachschaut, ob auch wirklich alle Objekte weg sind.

Der Baum wird ja nicht aufgeräumt. Er wird nur umorganisiert.

Und diesen Code zu reviewen brauch wahrscheinlich länger, als es gedauert hat ihn zu schreiben. Und das war schon ne ganze Weile. Das allein aufgrund einer reinen Vermutung zu machen bekomme ich nicht bezahlt, und ich kann den Aufwand auch nicht vor dem Kunden vertreten.

Sherlock 29. Mai 2008 10:39

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Dann wirst du wohl den harten Weg des realistischen gehen und regelmäßig neu starten müssen.

:?

Sherlock

alzaimar 29. Mai 2008 10:43

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Oh, das ist kniffelig:

1. Du hast den Code geschrieben, also: Schuld eigene, wenn Du nachsitzen musst.
2. Dann wird er eben umorganisiert. Du sollst ja nicht gleich den ganzen Code reviewen (obwohl das ne gute idee wäre, weil du dich verhaspelt hast).

Kannst Du denn entscheiden, ob ein Objekt 'dort' hingehört bzw. unberechtigterweise noch lebt? Wenn ja, nimm meinen Trick und suche halt immer wieder in der Objektliste (in der sich die Objekte bei der Instantiierung ja eingetragen haben) Objekten, die es nicht geben sollte. Von mir aus mit einem Timer, oder durch einen 'SCAN' Button oder sonstwas.

Phoenix 29. Mai 2008 10:52

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Es ist ja nichtmal raus ob das wirklich meine Schuld ist. Das ist ja das ganze Problem. Das kann auch irgendwo am Framework oder an was anderem liegen. Ich kann halt nur nicht ausschliessen, dass es bei mir liegt. Deswegen muss ich jetzt mit möglichst wenig Aufwand eine Aussage treffen können ob es an meinem Code liegt oder nicht.

Wenn nicht, bin ich nämlich fein raus und dann wissen wir, dass sich die Kollegen nochmal über ihre Sachen Gedanken machen müssen. Wenn es an mir liegt, dann ist der Aufwand eines Code-Reviews durchaus berechtigt und dann werden wir den auch machen. Nur jetzt eben nicht, weil es gut sein kann dass wir dann über ne Woche da dran sitzen, mit Bleistiftcompiler nochmal alles Nachrechnen und hinterher sagen: "Ne, ist alles okay hier. Das Problem liegt woanders." Und das darf eben nicht passieren.

Und nein. Den Baum einmal komplett zu traversieren ist aus Performancegründen nicht möglich, zudem ich dabei Jeden einzelnen Node mit jedem anderen vergleichen müsste, ob ich tatsächlich Duplikate habe die nicht mehr angegriffen werden. Der würde bei der Knotenanzahl Jahre rechnen..

Die Objektliste habe ich jetzt mal implementiert, und ich werde die jetzt regelmässig in ein File schreiben (Timestamp der Erzeugung, eine eindeutige Objekt-ID, der Klassenname und zusätzliche Identity-Informationen).

So kann ich durch die Änderungen in dem File hoffentlich mindestens sehen, ob später neue Objekte hinzukommen, die eigentlich andere Objekte ersetzen würden obwohl diese noch da bleiben.

DGL-luke 29. Mai 2008 10:53

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
dem kunden stellt sich dann eben die wahl, dich das ganze prüfen zu lassen, oder alle 3?6?12? Stunden alles komplett neu zu initialisieren.

Oder kannst du das ohne Neustart machen? EInfach selber mal alles neu initialisieren, sobald der speicher knapp wird (du 100.000 objekte in der db hast)?

Bei fragmentierung hilft das eventuell auch wenig; da musst du dir dann was einfallen lassen, wie du das vermeidest; wenn du einfach mal einen string mit 500MB größe anforderst und dann wieder nilst, sollte sich der Delphi-Speichermanager (ach ja richtig, ==fastmm ab delphi 2006) da am Ende des RAMs (oder des Pagefiles, das wär dann evtl. leicht kontraproduktiv) 500MB zusammengehörigen virtuellen speicher reservieren und nicht so schnell wieder (an windows) zurückgeben. da kann er dann ganz gemütlich deine objekte eins nach dem anderen reinlegen.

eine neuorganisation (komplette reinitialisierung deiner objekte) sollte dann dazu führen, dass erstmal der komplette 500MB speicherbereich bei delphi wieder als "frei, aber noch meins" interpretiert wird und die wieder neu erstellten objekte schön eins nach dem anderen wieder reingelegt werden.
EDIT: das führt aber dann zwischenzeitlich zu doppelter buchhaltung, d.h. du musst alle deine daten woanders hin wegschreiben, auf die festplatte o.ä..... denn du musst natürlich erst ALLES freigeben, bevor du dann ALLES wieder neu erstellst.

Aber das sind hier alles Sachen, die eigentlich ein Speichermanager von sich aus machen sollte. Ohne Low-Level-Sachen versuchen, den Speichermanager zu einem bestimmten Verhalten zu überreden, kann ordentlich in die Hose gehen.

alzaimar 29. Mai 2008 15:53

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Ich werde mal kurz drastisch. Nicht hauen.

Du lamentierst und drückst Dich um die Lösung :mrgreen:
Zitat:

Zitat von Phoenix
Es ist ja nichtmal raus ob das wirklich meine Schuld ist...Ich kann halt nur nicht ausschliessen, dass es bei mir liegt.

Dann sorge dafür, das es sicher ist, das es nicht deine Schuld ist. Entweder Du findest KEINEN Fehler, oder du FINDEST einen und REPARIERST ihn.
Zitat:

Zitat von Phoenix
Den Baum einmal komplett zu traversieren ist aus Performancegründen nicht möglich

Wieso? Du schreibst ein TEST-TOOL UM DEN FEHLER ZU FINDEN, da ist die Performance egal. Du willst schließlich den Fehler finden. Und Jahre rechnen würde der auch nicht. Wozu gibt es Hashmaps? Und selbst wenn Du für einen Scan 10 Stunden benötigst. Na und? Hinterher hast Du den/die Übeltäter!

Wie gesagt. Nicht hauen :mrgreen:

Phoenix 29. Mai 2008 16:14

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Neee, ich haue nicht. :mrgreen: Scheint wohl auch nicht nötig zu sein.

Dank Deiner Idee mit der zentralen Objekt-Liste konnte ich zumindest schonmal nachvollziehen, dass bei allen getesteten Konstellationen die Anzahl der instanzierten Objekte konstant bleibt. Die ID's erhöhen sich ständig, aber die Gesamtanzahl ist Konstant. Ergo bleibt beim umräumen und wegwerfen und neu Erzeugen nichts 'über'.

Allerdings wird da öfter umgeräumt, also kann es tatsächlich durch das ständige verkürzen und verlängern von den dynamischen Arrays die diese Objekte vorhalten zu einer Fragmentierung kommen. Wenn das das Problem ist muss ich halt auf TList umstellen. Das ist aber um längen einfacher.

himitsu 29. Mai 2008 22:24

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Oha. :-(
Davon wird (in diesem Fall leider) an manchen Stellen exzessiver Gebrauch gemacht.
dann laß dir doch mal die MemoryMap anzeigen ... da sollte man doch erkennen können, wie die fragmentierung aussieht.

Zitat:

Würde sich das Fragmentierungs-Problem mit dem FastMM lösen?
es kommt auf die Größe und Art der Speicheranfragen an.

allgemein kommt es bei kleinen änderungen z.B. eines dynamischen Arrays zu einer geringeren Defragmentierung, da dieser bei einem Realloc nich direkt die gewünschte Größe sofort ändert, sondern versucht es in größeren Schritten anzupassen.

generic 30. Mai 2008 23:58

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
nutzt du Com-Objekte?
z.B. MSHTML, ADO, MSXML?

Matze 31. Mai 2008 09:32

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Zitat:

Zitat von generic
nutzt du Com-Objekte?

Zitat:

Zitat von Phoenix
Nein, ich benutze kein Com (zum Glück).

;)

Phoenix 31. Mai 2008 09:44

Re: Wie kann man ein "halbes" Memory-Leak finden?
 
Hehe Generic, das hattest Du doch schonmal gefragt *g*

Also, stand zum WE:
Wie schon gesagt: Die Anzahl der Objekte bleibt immer Konstant.

Was ich interessant fand: Die Anwendung holt sich initial beim Starten ca. 40 MB Speicher. Wird sie minimiert fällt dieser Speicherverbraucht drastisch ab: unter 1 MB! Maximiere ich sie wieder, holt sie sich dann wieder ca. 20 MB und wächst langsam aber stetig wieder an.
Ich find diesen Unterschied leicht krass. So ein Verhalten beobachte ich bei vielen Anwendungen, aber von 40 auf unter 1 MB hat es noch keine andere Applikation geschafft.

Sind das einmal angezeigte, aber dann nicht mehr verwendete Gui-Elemente wie z.B. Grafiken die dann ggf. von Windows weggeschmissen werden?

Naja.. am Montag geht die Suche weiter.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:15 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