Frage

Ich habe eine Anwendung, die aus einer großen Anzahl von MSMQ-Warteschlangen liest (derzeit etwa 10.000).ich benutze queue.BeginPeek mit UInt32.MaxValue-Timeout zum Empfangen von Nachrichten aus der Warteschlange.Wenn die Nachricht in der Warteschlange erscheint, verarbeite ich sie und rufe an queue.BeginPeek wieder.Ich höre also alle Warteschlangen ab, aber die Nachrichtenverarbeitung erfolgt im Thread-Pool.

Mir ist aufgefallen, dass die Speichernutzung langsam zunimmt (zwei Wochen Arbeit führen zu einem Anstieg von 200 MB auf 800 MB).Nachdem ich die Dump-Datei untersucht habe, sehe ich ein typisches Heap-Fragmentierungsbild mit vielen freien Objekten (einige davon haben eine Größe von etwa mehreren Megabyte).Und zwischen den Löchern befinden sich festgeklemmte Gegenstände.

Dies scheint eine häufige Situation zu sein, wenn mit Aufrufen von nicht verwaltetem Code gearbeitet wird, die angeheftete Objekte erstellen.Aber ich habe im Internet keine Lösung gefunden.

Ist die Speicherverwaltung in .NET also so rein, dass nicht einmal so einfache Szenarien durchgeführt werden können, oder übersehe ich etwas?

Bearbeiten : Ich habe einige Untersuchungen in Beispielanwendungen durchgeführt.Die Lücken (freie Speicherzonen, sogenannte freie Objekte) zwischen angehefteten Objekten werden von GC wiederverwendet, wenn Speicher für neue Objekte zugewiesen wird.Aber in meiner Produktionsanwendung sind angeheftete Objekte langlebig und erscheinen schließlich in der 2. Generation mit den Löchern dazwischen (weil GC nur die Grenze verschiebt, die Generationen trennt).Da ich nur sehr wenige normale, langlebige Objekte habe, sehe ich diese Lücken in der Dump-Datei der 2. Generation.

Daher kann der Speicherverbrauch meiner Anwendung auf 10.000* ansteigen (durchschnittliche Größe der Lücke).(10000 ist die Anzahl der Warteschlangen, die in Zukunft auch zunehmen kann).Ich habe im Moment keine Ahnung, wie ich das beheben kann.Die einzige Möglichkeit besteht darin, die Anwendung von Zeit zu Zeit neu zu starten.

Wieder einmal kann ich nur fragen, warum .NET keinen separaten Heap für angeheftete Objekte hat?(Vielleicht ist das eine Anfängerfrage).Im Moment sehe ich, dass der Aufruf von asynchronen Vorgängen, die mit nicht verwaltetem Code funktionieren, zu Speicherproblemen führen kann.

War es hilfreich?

Lösung

Nachdem Sie sich den Quellcode für den verwalteten Wrapper für MSMQ angesehen haben, scheinen Sie bei der Verwendung der API auf ein echtes Problem gestoßen zu sein.Berufung BeginPeek erstellt eine Sammlung von Eigenschaften, die dann angeheftet werden, bevor sie an die nicht verwaltete API übergeben werden.Erst wenn eine Nachricht empfangen wird, werden diese Eigenschaften nicht mehr angeheftet. Um weiterhin Nachrichten zu erhalten, müssen Sie jedoch anrufen BeginPeek An diesem Punkt führt dies im Laufe der Zeit zu einer Fragmentierung des Speichers.

Wenn diese Fragmentierung wirklich besorgniserregend ist, kann ich mir nur vorstellen, dass Sie alle Anrufe etwa stündlich abbrechen sollten BeginPeek, erzwingen Sie eine Speicherbereinigung und setzen Sie dann den normalen Abhörvorgang fort.Dies sollte es dem Garbage Collector ermöglichen, die Fragmentierung zu bewältigen.

Andere Tipps

Nun, wenn es sich um ein Problem mit der Langlebigkeit der angehefteten Objekte handelt, besteht eine einfache Problemumgehung darin, eine Zeitüberschreitung für die Objekte zu verwenden BeginPeek mit einer kürzeren Dauer, um zu verhindern, dass sie in die nächste Generation übergehen.Nach jeder Auszeit und EndPeek Sie können das erneut ausstellen BeginPeek.Abhängig davon, wann die von Martin genannten Eigenschaften erstellt und verworfen werden, müssen Sie möglicherweise das Warteschlangenobjekt neu erstellen (natürlich nicht die Warteschlange selbst, sondern nur den geänderten Wrapper).Mit etwas Glück müssen Sie es jedoch nicht so weit bringen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top