2015-05-14 5 views
5

Meine IIS-Anwendung (.NET 4.0, IIS7) wächst ständig im Speicher und fällt schließlich um, als ob ich ein Speicherleck hätte.w3wp.exe Garbage Heap ist voll von freiem Objektraum und wächst weiter

Also nahm ich ein DMP, während es um 1,7GB war und öffnete es in WinDbg.

Der dumpheap -stat Befehl zeigte, dass, während ich eine ganze Menge von Objekten im Heap hatte, die Mehrheit (und etwas, das wächst, wenn sie bei sequentiellen DMPs suchen) als „Free“ (> 800 MB) markiert:

000007feef55b768 46091 2212368 System.Data.DataRowView
000007fe9739dda8 10355 2236680 Newtonsoft.Json.Serialization.JsonProperty
000007fef4260610 33062 2644960 System.Signature
000007fef4242250 41809 4682608 System.Reflection.RuntimeMethodInfo
000007fef424f05 8 69232 8847997 System.Byte []
000007fef4241b28 11 9.437.680 System.Double []
000007fef4237ca0 15 9.505.176 System.DateTime []
000007fef424c168 32559 11.009.308 System.Char []
000007fef424dc30 17271 11.795.376 System.Int32 []
000007feef555c48 908 17936672 System.Data.RBTree`1 + Knoten [[System.Int32, mscorlib]] []
000007feef554f58 853 22056952 System.Data.RBTree`1 + Knoten [[System.Data.DataRow, System.Data]] []
000007feef5514b0 541444 51978624 System.Data.DataRow
000007fef424aee0 1550958 132599872 System.String
000007fef422f1b8 183.607 178.409.288 System.Object []
0000000000d8b2d0 234.017 844.500.226 Freie

Also lief ich dann "! Dumpheap Freie -Typ", die mir eine viel winziger Freie Objekte gab (94 Bytes jeweils zu sei genau!) Und gegen Ende ein paar größere "Free" Objekte:

00000003098a59b0 0000000000d8b2d0 134 Freie
00000003098c19d0 0000000000d8b2d0 102 Freie
00000003098ffa00 0000000000d8b2d0 54 Frei
0000000309a41d98 0000000000d8b2d0 5.961.750 Freie
000000041f8a1000 0000000000d8b2d0 24 Frei
000000042001b4d0 0000000000d8b2d0 16933078 Frei
00000004211bf7c8 0000000000d8b2d0 7702 Frei
00000004212c1600 000000 0000d8b2d0 35173374 Freie
00000004236b3be0 0000000000d8b2d0 66886 Freie
0000000423cc41e8 0000000000d8b2d0 10778318 Freie
0000000424768928 0000000000d8b2d0 2254734 Freie
00000004249ec128 0000000000d8b2d0 21166350 Freie
000000042600f1e0 0000000000d8b2d0 51366 Freie
000000042621bac8 0000000000d8b2d0 114007238 Freie

Statistics: 
       MT Count TotalSize Class Name 
000007fef31e7460  1   32 System.Net.SafeLocalFree 
0000000000d8b2d0 234017 844500226  Free 
Total 234018 objects 

Anbetracht dessen, die sich wiederholende Anzeige Kleid von "d8b2d0" Ich lief zu einem "gcroot d8b2d0!" denen ich folgendes Ergebnis bekam:

0: '! gcroot -all' 000> gcroot d8b2d0
Gefunden 0 einzigartige Wurzeln (Lauf sehe alle Wurzeln).

Also ... nach all dem ... Ich habe Massen von freien Objekten auf meinem Haufen stecken, die der GC nicht freigibt. Dies baut sich in etwa 2-3 Stunden auf. Es gibt kein anderes Anzeichen von Speicherlecks von tatsächlichen typisierten Objekten. Es passiert über fast alle unsere VMs in der Produktion.

Hat jemand eine Idee, wie man mit dem GC umgehen kann, so viel Freiraum auf dem Heap lassen?

Es hat mich tagelang im Kreis laufen lassen. Also, ist das Genie, das mir helfen kann, dieses herauszufinden!

+0

Ist dies eine Asp.Net-Anwendung? Irgendein bestimmter Rahmen oder eine benutzte Bibliothek? – ljubomir

+0

Ja, es ist asp.net. Es ist meistens DataTables und einige lokale WCF mit net.pipe. – StackedActor

+0

Haben Sie einen Interop-Code oder einen Code, der 'GCHandle's direkt zuweist? Ich denke, dass Sie vielleicht eine Menge * gepinnter * Objekte haben, die eine Verdichtung verhindern. –

Antwort

1

Dank dem Vorschlag zur Verwendung von PerfView von magicandre1981, und nach etlichen sehr großen Speicherabbildern, habe ich dieses Problem auf die Verwendung von DataRow.DefaultIfEmpty() in einem Linq-Ausdruck gefunden. Es war Teil einer Unterstützungsfunktion zum Ausführen eines LeftJoins zwischen zwei DataTables.

Mit der DefaultIfEmpty() in der DataRow-Enumeration als Teil der Linq-Ausdruck könnte ich Speicher Sky-Rocking zu 4GB + in Minuten neu erstellen. Der größte Teil davon bleibt bis zur Gen2-GC-Sammlung durch die Menge an ItemArrayObjects erhalten, die erstellt werden (sowohl kleiner als auch großer Objekt-Heap). Dies wiederum führt zu einem stetig steigenden Wertbeitrag. Die GC2-Sammlung kann auf dem kleinen Haufen einfach nicht mithalten, und der große Haufen leidet unter einer (wenn überhaupt) geringen Wiederverwendung.

Wir haben diesen Aufruf genommen und die gleiche Erholung wird nie mehr als 50MB in festgeschriebenem Speicher bekommen. Wir müssen jetzt sehen, wie sich das auf unsere DataTable-Joins auswirkt, aber das Memory-Heap-Rätsel wurde gelöst!

Danke für die Hilfe Leute.

0

Wenn Sie sicher sind, dass Ihre App einen Speicherverlust aufweist, würde ich vorschlagen, dass Sie die lokale Analyse mit dem Speicherprofiler starten. Dies könnte die Ursache des Problems schneller aufdecken als die Analyse von Speicherauszügen in der Produktion.

+0

Danke für den Vorschlag. Ich habe all das durchgemacht. Es gibt keine Speicherverluste, was dazu geführt hat, dass ich stattdessen eine Speicher-DMP-Datei untersucht habe. Aus der obigen Analyse bestätigt sich (ich glaube), dass es tatsächlich kein Speicherleck gibt. Ansonsten hätte das große 800MB + Chunk einen gcroot oder zumindest einen Objekttyp. Stattdessen wird es tatsächlich als * frei * bezeichnet, aber der GC wird es nicht veröffentlichen !? – StackedActor

Verwandte Themen