Wie kann ich die Garbage Collector-Leistung von .NET 4.0 in hochkonkurrierendem Code verbessern?

Ich verwende die Task Parallel Library aus .NET Framework 4 (speziellParallel.For undParallel.ForEachIch erhalte jedoch äußerst mittelmäßige Beschleunigungen, wenn ich einige Aufgaben parallelisiere, die so aussehen, als ob sie auf einem Dual-Core-Rechner problemlos parallelisiert werden sollten.

Bei der Profilerstellung des Systems sieht es so aus, als ob aufgrund des Garbage Collectors viel Thread-Synchronisation stattfindet. Ich verteile viele Objekte. Daher frage ich mich, wie ich die Parallelität verbessern und gleichzeitig das Umschreiben meines Codes minimieren kann.

Zum Beispiel gibt es einige Techniken, die in dieser Situation nützlich sein können:

Sollte ich versuchen, den GC manuell zu verwalten?Soll ich verwendenDispose?Soll ich Objekte anheften?Sollte ich andere unsichere Code-Tricks machen?

NACHSATZ:

Das Problem ist, dass der GC nicht zu oft ausgeführt wird, sondern dass verhindert wird, dass gleichzeitiger Code effizient parallel ausgeführt wird. Ich halte "weniger Objekte zuweisen" auch nicht für eine akzeptable Antwort. Dazu muss zu viel Code neu geschrieben werden, um einen schlecht parallelisierten Garbage Collector zu umgehen.

Ich habe bereits einen Trick gefunden, der der Gesamtleistung geholfen hat (mit gcServer), aber es hat die gleichzeitige Leistung nicht geholfen. Mit anderen WortenParallel.For war nur 20% schneller als eine serielle For-Schleife, bei einer peinlich parallelen Aufgabe.

POST-POSTSCRIPT:

Okay, lassen Sie mich weiter erklären, ich habe ein ziemlich großes und komplexes Programm: einen optimierenden Interpreter. Es ist schnell genug, aber ich möchte, dass seine Leistung bei parallelen Aufgaben (primitive Operationen, die in meine Sprache integriert sind) skaliert wird und mehr Kerne verfügbar sind. Bei den Auswertungen teile ich viele kleine Objekte zu. Das gesamte Interpreter-Design basiert auf allen Werten, die von einem einzelnen polymorphen Basisobjekt abgeleitet werden. Dies funktioniert in einer Single-Thread-Anwendung sehr gut, aber wenn wir versuchen, die Task Parallel Library auf parallele Auswertungen anzuwenden, gibt es keinen Vorteil.

Nach einer Menge Nachforschungen, warum die Task Parallel Library die Arbeit für diese Aufgaben nicht richtig auf die Kerne verteilt hat, scheint der Täter der GC zu sein. Anscheinend scheint der GC wie ein Flaschenhals zu wirken, weil er eine Synchronisation hinter den Kulissen durchführt, die ich nicht verstehe.

Was ich wissen muss ist: Was genau macht der GC, was dazu führen kann, dass stark gleichzeitiger Code schlecht funktioniert, wenn er viele Zuweisungen vornimmt, und wie wir das umgehen könnenaußer geradeweniger Objekte zuweisen. Dieser Ansatz ist mir bereits in den Sinn gekommen und würde ein erhebliches Umschreiben einer Menge Code erfordern.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage