Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
WinDbg: Wo ist der Speicher hin?
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

Themenstarter:

WinDbg: Wo ist der Speicher hin?

beantworten | zitieren | melden

Hallo,

ich habe ein Programm geschrieben das jetzt schon ein paar Monate unterbrechungsfrei läuft.
Das Programm hat sich dabei immer weiter mit Speicher vollgezogen und hat inzwischen 1,6 GB an speicher unter beschlag. Ich habe mir einen Dump gemacht und den mit WinDbg analysiert (Was das angeht habe ich leider nur einen sehr begrenzten Wissensstand)

Wenn ich nun einen !dumpheap -stat ausführe sind die letzten Zeilen folgende

              MT    Count    TotalSize Class Name
.
.
.
000007fee7852688      712        79744 System.Reflection.RuntimeMethodInfo
000007fee785f508     1011        80880 System.Collections.Hashtable
000007fee785e068      861        98300 System.Int32[]
000007fee78c19e0     1998       111888 System.Diagnostics.StackFrame
000007fee62c3550     1652       158592 System.Diagnostics.NtProcessInfoHelper+SystemThreadInformation
000007fee785b0b0     1013       256368 System.Collections.Hashtable+bucket[]
000007fee785d608     5523       309288 System.RuntimeType
000007fee785c5a0      355       371212 System.Char[]
000007fee783f5e0     5105       792776 System.Object[]
000007fee785f490      233       929502 System.Byte[]
000007fee785b318     9773      1157990 System.String
000007fee784d6e8       14      1812040 System.Int64[]
0000000000437260      104      2654270      Free
Total 54509 objects
Fragmented blocks larger than 0.5 MB:
            Addr     Size      Followed by
00000000015f8bc0    1.8MB 00000000017c6f50 System.SByte[]



Also wie man sieht nicht die Bohne von hinweis wo meine 1,6 GB hin sind.. Der dürfte sich eigentlich nur ein paar MB nehmen. Ich vermute das eventuell native Sachen sind die da den Speicher blockieren.. Aber wie bekomme ich so etwas raus?

Speicher ist noch genug da, somit kann ich mir auch vorstellen das der GC mir da ein Schnäppchen spielt.. aber 1,6 GB?? Ich habe mich auch schon mit Just Trace von Telerik an den Process gehängt und einen GC run erzwungen.. -> nichts.

Vllt kann mir jemand einen Hint geben wo ich noch schauen kann.

Grüße
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von unconnected am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo unconnected,
Zitat
Speicher ist noch genug da, somit kann ich mir auch vorstellen das der GC mir da ein Schnäppchen spielt.. aber 1,6 GB??
das kann schon sein, denn der GC verfolgt grundsätzlich die Strategie, Speicher erst dann freizugeben, wenn er anderweitig benötigt wird. Und wenn noch genug freier Speicher da ist, dann stören die belegten 1,6GB ja keinen (außer dich, weil du nicht weiß, ob ich mich vielleicht doch irre und daher dem Prozess irgendwann doch der Speicher ausgeht).

Du könntest einen anderen Prozess starten, der viel Speicher allokiert und schauen, ob der GC des eigentlichen Prozesses dann tätig wird. Allerdings mit der Gefahr, dass es dadurch vorzeitig zu einer OutOfMemoryException kommt.

Die Anzeige des Speicherverbrauchs im Task-Manager ist allerdings sowieso nicht verlässlich, wobei ich vergessen habe, was der Grund dafür ist. In älteren Forenbeiträgen zum GC sollte sich allerdings eine Begründung finden lassen.

herbivore
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16205

beantworten | zitieren | melden

Naja die erste Sache ist, dass der TaskManager nicht nur die eigenen Ressourcen zum Speicher dazu rechnet, sondern auch externe, die der Garbage Collector gar nicht behandelt bzw. behandeln darf (eben irgendwelches Win32/COM-Zeugs). Dann läuft der GC in nem eigenen Thread, sodass er immer auf die anderen Threads warten muss, damit er überhaupt analyisieren kann und weiß, was er abräumen darf und was nicht. Daher ist ein manueller Eingriff auch "so teuer".
Intern kategorisiert er dann Objekte/Datencontainer nach ihren Typen und der Langlebigkeit, sodass manche Dinge früher entgültig verworfen werden, als andere.

Zum Problem: es gibt den sogenannten CLR Profiler . Das Ding ist zwar alt und unkomfortabel, aber man findet schon ein paar Dinge mehr als bei anderen Profilern.

Mal FxCop über Deinen Code laufen lassen?
Der zeigt Dir ziemlich gut, wo Du bestimmte Dinge gar nicht oder falsch verwirfst. Gerade beim IDispose machen manche dann doch einige Fehler.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

Themenstarter:

beantworten | zitieren | melden

Hallo,

danke ersteinmal für die antworten.

Telerik Just Trace ist sozusagen die Luxusvariante von CLR Profiler.. zeigt aber auch nicht mehr Speicher an als WinDbg.

FxCop werde ich mal Probieren.
Zitat
bzw. behandeln darf (eben irgendwelches Win32/COM-Zeugs).

Gibt es eine möglichkeit genau das zu analysieren?

Ich glaube ich werde mir dann ersteinmal den Speicherdump im hexeditor anschauen. Wenn ich da in der Mitte anfange sollte die Wahrscheinlichkeit das eins von den tatsächlich gelisteten Objecten treffe doch recht gering sein.. bei 1,6 GB Vllt gibt da irgendwelche verdächtigen strings..
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16205

beantworten | zitieren | melden

Ich kenn die gängigen Profiler; aber zumindest bis vor kurzem konnten auch die "modernen" nich alles das bzw. haben nich alles collected, wie der CLR Profiler.
Aber wie Du willst...

Und ne, 100% genau analyisieren kannste das leider nicht.
Du könntest höchstens auf Tools zurück greifen, wie den Speicher und dessen Herkunft analysieren, also etwas anders funktionieren als die klassischen Profiler. Wenn mir jetzt der Name einfallen würde...
Wenn ich mit nem Profiler nicht mehr klar komme, weil er irgendwas nicht findet, verwende ich auch mal gern "Process Hacker" um auch die Heaps etc sehen zu können.
Über perfmon.exe kannste Dir auch genau anschauen, warum der RAM hoch ist. Also welche Art von Memory (Virtual, Working, Pooled, Private, Paged..) er denn wie viel verwendet.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7572
Herkunft: Waidring

beantworten | zitieren | melden

Hallo Abt,
Zitat
Du könntest höchstens auf Tools zurück greifen, wie den Speicher und dessen Herkunft analysieren
Wenn ich das jetzt richtig verstanden habe, so geht das eh mit dem CLR Profiler indem "Snapshots" verglichen werden.

mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16205

beantworten | zitieren | melden

Mh.. kann sein
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

Themenstarter:

beantworten | zitieren | melden

Hallo zusammen,

denke ich habe den Verursacher gefunden. Aber die Umsetzung und Test muss ich leider schieben.

Das Problem bei Clr Profiler und JustTrace ist, das sie nur den managed heap darstellen. genauso verhält es sich bei winDbg !dumpHeap -stat. Da waren immer nur ein paar Megabyte drin.

Mit dem Tool DebugDiag konnte ich nun sehen welcher Heap zu groß (Microsoft VC Runtime Heap) ist und welche Adressen dieser für sich beansprucht, die ich mir wiederrum mit WinDbg anschauen konnte.

In diesen Speicherbereichen habe ich diverse Texte von Oracle fehlermeldungen und Xml Daten von Aufträgen die schon Monate vorher abgearbeitet bzw. der Datenbank übergeben worden sind. Die größten Bereiche waren einfach nur 0x00.

Hilfreich bei der Suche war folgender Link: Walkthrough - Troubleshooting a native memory leak

Somit werde ich als nächste Maßnahme ersteinmal den Oracle Treiber gegen den von Devart austauschen. Ich denke das sich dann mein Problem auflöst.

Danke nocheinmal für die Hilfe.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von unconnected am .
private Nachricht | Beiträge des Benutzers