2012-04-12 12 views
4

Ich versuche, einige Speicherauslastungsprobleme zu beheben. Insgesamt sammelt meine Anwendung ein paar Datenwerte und visualisiert sie mit einem C1 WPF Charts und Datagrids schließlich alles in PDF-Berichte..NET-Prozessspeicherauslastung = 5x CLR-Heapspeicher?

Profilerstellung meines Prozesses mit YourKit Ich bin mit der Situation konfrontiert, dass die CLR-Heap-Größe ~ 120 MB ist (was alles in Ordnung ist), während die Prozessspeichergröße ~ 580 MB beträgt. Das ist fast 5-mal der Speicherverbrauch meiner tatsächlichen CLR-Heap-Größe. Meine CLR-Peak-Größe war 220 MB gegenüber 710 MB Prozessspeicherzuweisung.

Ich bin mir bewusst, dass einige Overhead auf meinem Objekt Haufen, Stapeln und so weiter erforderlich ist. In Java-JVMs war der typische Faktor, um den ich mich gekümmert habe, ~ 1,5x.

Wie kann dieser übermäßige Speicheraufwand erklärt werden? Ordnen die Prozesse nur freien freien Heapspeicher zu? Wenn ja, erklärt dies die 710 MB im Vergleich zu 220 MB?

Antwort

11

Ein paar zusätzliche Hinweise hier. Obwohl ich nicht sicher bin, was Sie mit "CLR Heap Size" meinen. Es ca. 8 verschiedenen Haufen, die die CLR verwendet - so dass der Speicher sehen Sie in der Heap-Größe vs. VM Größe Konten für einige der Differenz:

  1. Loader Heap: enthält Strukturen CLR und das Typsystem
  2. Hochfrequenz-Heap: Statik, MethodTables, FieldDescs, Interface-Karte
  3. Low Frequency Heap: EEClass, Classloader und Lookup-Tabellen
  4. Stub Heap: Stubs für CAS, COM-Wrapper, P/Invoke
  5. Large Object Er ap: Speicherzuordnungen, die mehr als 85k Byte
  6. erfordern
  7. GC Heap: Benutzer zugewiesen Heap-Speicher privat an die App
  8. JIT-Code Heap: Speicher zugewiesen durch mscoreee (Execution Engine) und der JIT-Compiler für verwalteten Code
  9. Prozess/Base-Heap: Interop/unmanaged Zuweisungen, nativen Speicher usw.

Zwei andere Gegenstände, die übermäßige Speichernutzung sind Speicherfragmentierung verursachen kann (meist auf der LOH auftritt oder große Objektheap) oder eine hohe Anzahl von Threads.

Es gibt viele Ursachen für die Speicherfragmentierung, und die beste Möglichkeit, dies auszuschließen, besteht darin, WinDbg zum Analysieren der Segmentgrößen für jedes Segment auf dem GC Heap zu verwenden.

Für eine große Anzahl von Threads steht Ihnen für jeden Thread, den Ihre App verwendet, 1 MB Stapelspeicherplatz zur Verfügung. Dieser Speicher befindet sich im Prozess/Basis Heap. Wenn Sie also 100 Threads haben, haben Sie zusätzliche 100 MB Speicherverbrauch.

HTH

+0

Vielen Dank für Ihre wertvollen und ausführlichen Notizen. in Bezug auf die Anatomie und mögliche Probleme in Bezug auf .NET-Speicherzuweisung. In meinem Fall stellte sich schließlich heraus, dass es sich um die C1-Grafikkomponente handelte, die große Speicherblöcke über GDI + verwendete. Als Java-Experte war ich völlig verwirrt, dies mit .NET-Speicher-Profiler-Tools nicht sehen zu können. Schließlich mussten wir dieses Problem umgehen/lösen, indem wir die Verwendung dieser C1-Grafikkomponenten einschränken. –

+0

Ich bin froh zu helfen. Ich musste viele Speicherauszüge mit WinDbg debuggen, was mir einiges beigebracht hat. Bei der Arbeit mit Komponenten von Drittanbietern behalte ich zwei Dinge im Auge: Erstens, vergewissere dich, dass sie entsorgt werden, und zweitens, behalte die Anzahl der Griffe im Auge, die deine App benutzt. Dies kann einfach getan werden, indem entweder TaskManager (stellen Sie sicher, dass die Handles-Spalte sichtbar ist) oder der SysInternals ProcessExplorer verwendet wird. Normalerweise würden Sie eine 'using()' Anweisung verwenden, um sicherzustellen, dass die Komponenten zeitgerecht entsorgt werden. Ich kenne WPF jedoch nicht, daher könnte das Framework schon dafür sorgen. –

+0

Ben, wie hast du herausgefunden, dass der GDI + Speicher verbraucht hat? – RollRoll

2

Wenn die Gesamtgröße der verwalteten Heaps erheblich kleiner ist als die von Ihrer Anwendung verwendeten privaten Bytes, weisen Sie wahrscheinlich nicht verwalteten Speicher zu und verwahren ihn (möglicherweise) nicht ordnungsgemäß. Grafikobjekte, Streams und andere Objekte, die IDisposable implementieren, müssen ihre Dispose()-Methode aufgerufen haben, bevor sie außerhalb des Gültigkeitsbereichs liegen oder in einer using(){}-Anweisung platziert werden, damit alle nicht verwalteten Ressourcen bereinigt werden. Ein Tool wie ANTS Memory Profiler kann Ihnen zeigen, wie Ihr Speicher zugewiesen wird und welche Objekte IDisposable implementieren.

+0

Danke Dan!Dies ist genau der Zeiger, den ich vermisst habe. Wahrscheinlich wird auch ANTS hier nicht helfen (ich habe YourKit bereits benutzt), da es nicht gemanagte Speicherlecks nicht verfolgen kann. Zur Zeit versuche ich mein Problem mit DebugDiag 1.2 zu beheben. –

+0

Ich bin nicht vertraut mit DebugDiag, aber AQTime von Smartbear ermöglicht es Ihnen, sowohl verwalteten als auch nicht verwalteten Code zu profilieren. Es ist nicht so einfach zu verwenden wie ANTS, aber es gibt mehr Informationen zur Verfügung. Siehe http://smartbear.com/products/qa-tools/application-performance-profiling –

Verwandte Themen