Wie Sie verhindern, dass asynchroner TCP-.NET-Code die Ressourcen eines ganzen Systems verbraucht

8

In einigen asynchronen tcp-Server-Code habe ich gelegentlich einen Fehler, der dazu führt, dass der Prozess den gesamten Systemspeicher belegt. Beim Betrachten der Protokolle, der Ereignisanzeige und einiger MS-Dokumente tritt das Problem auf, wenn "die aufrufende Anwendung asynchrone IO-Aufrufe an die Wenn der Remoteclient sein E / A-Ende beendet, führt dies zu Spikes bei der Speicherbelegung und beim Fixieren von System.Threading.OverlappedData-Struct- und -Byte-Arrays.

>

Die vorgeschlagene Lösung des KB-Artikels besteht darin, "eine Obergrenze für die Menge der ausstehenden Puffer (entweder senden oder empfangen) mit ihrem asynchronen IO festzulegen."

Wie macht man das? Bezieht sich dies auf das Byte [], das in BeginRead gesendet wird? Also ist die Lösung, die einfach Zugangsbyte [] mit einem Semaphor umschließt?

BEARBEITEN: Semaphorgesteuerter Zugriff auf Byte-Puffer oder einfach das Vorhandensein eines Pools von Byte-Puffern mit statischer Größe sind zwei gebräuchliche Lösungen. Eine Sorge, die ich immer noch habe, ist, dass, wenn dieses asynchrone Client-Problem auftritt (vielleicht ist es tatsächlich ein merkwürdiges Netzwerkereignis) Semaphoren oder Byte-Puffer-Pools verhindern, dass mir der Speicher ausgeht, aber es löst das Problem nicht. Mein Pool von Puffern wird wahrscheinlich von dem / den Problem-Client (s) verschlungen, wodurch die korrekte Funktion der legitimen Clients gesperrt wird.

BEARBEITEN SIE 2: Kam über diese große Antwort . Im Grunde zeigt es, wie man Objekte manuell löst. Und während der asynchrone TCP-Code die Run-Rules hinter den Kulissen festhält, könnte es möglich sein, dies zu überschreiben, indem jeder Puffer vor der Verwendung explizit angeheftet und dann am Ende des Blocks oder in einem finally-Modus entfernt wird. Ich versuche das jetzt herauszufinden ...

    
kmarks2 21.05.2012, 13:37
quelle

1 Antwort

3

Eine Möglichkeit, das Problem zu lösen, ist die Vorbelegung von Puffern und anderen Datenstrukturen, die in der asynchronen Kommunikation verwendet werden. Wenn Sie beim Start eine Vorabzuordnung vornehmen, wird keine Fragmentierung auftreten, da sich der Speicher natürlich im selben Bereich des Heapspeichers befindet.

Ich empfehle die Verwendung von ReceiveAsync / SendAsync APIs, die zu .Net 3.5 SP1 hinzugefügt wurden. Dadurch können Sie die SocketAsyncEventArgs -Struktur und den Speicherpuffer, der in SocketAsyncEventArgs.Buffer property gespeichert ist, im Cache zwischenspeichern oder vorbelegen BeginXXX / EndXXX APIs, die nur das Zwischenspeichern oder Vorabzuweisen des Speicherpuffers zulassen.

Bei der Verwendung der alten API traten auch erhebliche CPU-Kosten auf, da die API Windows-überlappte E / A-Strukturen intern immer wieder neu erstellte. In der neuen API geschieht dies in SocketAsyncEventArgs , und durch das Poolen dieser Objekte werden die CPU-Kosten nur einmal bezahlt.

Was Ihr Pinning-Update angeht: Das Pinning ist aus einem bestimmten Grund da, nämlich um zu verhindern, dass GC den Puffer während der Defragmentierung bewegt. Durch das manuelle Entfernen können Sie Speicherbeschädigungen verursachen.

    
Teleo 28.05.2012, 20:40
quelle

Tags und Links