Ich verwende ausgiebig eine verschachtelte Datenstruktur basierend auf parallelen Arrays ( SCG.SortedList<K,V>
, sieht wie Outer<K, Inner<K_delta,V>>
aus) und eine Berechnungsmaschine, die die Strukturen sehr oft kopiert. Die Größe der Strukturen kann sehr unterschiedlich sein und viele von ihnen werden in LOH sein, weil - auch wenn sie bereits verschachtelt sind - entweder innere oder äußere lang genug sind und die Werte meist verdoppelt sind (für das Doppelte ist die Grenze 1000 Elemente) pro Array, nach dem es zu LOH geht, zumindest auf x86).
Der Anwendungsfall für die verschachtelte Datenstruktur besteht darin, Hochfrequenzdaten in einem lang andauernden Prozess zu akkumulieren. Ich könnte es als einen Puffer verwenden, um die Daten zu aggregieren und nur ein minimales Fenster für die Aggregation zu behalten (durch Ablegen älterer innerer Listen und Beschneiden der äußeren Liste), aber dieses Kopieren / Trimmen könnte LOH-Fragmentierungsprobleme verursachen und mehr Speicherplatz beanspruchen Speichern Sie es.
Nachdem ich tiefer über die LOH Fragmentierung gelesen habe, könnte ich meinen, dass ich eine LOH Fragmentierung haben werde, denn was häufig in meinem Prozess / Berechnungen passiert, ist genau das, was zB in a beschrieben ist href="https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/"> großer Artikel über LOH Zersplitterung von Andrew Hunter : Erstellen, nach Zufallsschritt vergrößern, Arrays kopieren ...
Allerdings kann ich nicht verstehen, ob die LOH-Fragmentierung auf der 64-Bit-Plattform überhaupt ein Problem ist? Im letzten Kommentar zum selben Artikel legt ein Kommentator nahe, dass auf LOH-Fragmentierung fast die gesamte 64-Bit-Plattform existiert kein Problem, weil der Adressraum so groß ist, dass es in der Realität schwer ist, ihn zu erschöpfen, während Speicherlöcher / leere Seiten nicht durch echten Speicher belegt sind. (Eine andere Option ist, dass MS beim Entwerfen von GC schlecht ausgefallen ist).
Könnte ein Experte bestätigen, dass diese Aussage im Kommentar für .NET verwalteten Speicher wahr ist? Stimmt es, dass LOH-Fragmentierung auf 64-Bit-Systemen nicht etwas ist, worüber man sich Sorgen machen sollte In den meisten Fällen wegen extrem großen Adressraum? Beim Schreiben dieser Frage habe ich eine Bestätigung für C ++ gefunden , daher ist diese Frage speziell für verwalteten Speicher in .NET gedacht. p>
Die zweite Frage ist , wie es für 32-Bit-Prozesse funktioniert, die auf 64-Bit-Systemen laufen ? Gilt das gleiche für beide, oder 32-Bit-Prozesse könnten ziemlich schnell aus dem Speicher laufen, wenn LOH-Fragmentierung vorliegt? (z. B. für Excel-Add-Ins bin ich auf 32-Bit-Architektur beschränkt, sogar auf 64-Bit-Systemen, für eine lange Zeit aufgrund von Legacy-Add-Ins herum)
Der Kommentar aus dem verlinkten Artikel ist unten:
Seitencache Geschrieben von: TruePath Gepostet am: Donnerstag, 24. November 2011 um 6:50 Uhr Nachricht:
Entweder benutzt du ein altes OS / CPU, die 64-Bit-Adressierung nicht unterstützt (oder eine billige Version von Gewinn 7) oder MS hat es radikal verfehlt, 64 Bit richtig zu nutzen Adressierung.
Win 7 ultimate lässt einen Prozess bis zu 192 Gigs, Schneeleopard, ansprechen 16 TB und 32 Exabyte. Sie werden nie realistisch kauen durch den gesamten Adressraum im LOH. Also die Strategie, die MS für die Zuweisung implementiert klingt wie die richtige und es ist nur ein künstliches Limit, das in die Quere kommt.
Denken Sie daran, nur weil Sie eine Seite mit Speicher zugeordnet haben bedeutet nicht Das Betriebssystem muss dies immer mit einer Seite RAM sichern. Das Betriebssystem ist vollkommen frei, um Seiten auf die Festplatte zu wechseln oder leere Seiten zu lassen unbesetzt. Die LOH sollte eine ganze Zahl von PSGs (4K) zuweisen für jedes Objekt. Wenn ein Objekt in der LOH durch den GC freigegeben wird, wird der Seiten, die ihm zugewiesen sind, sollten an das Betriebssystem zurückgegeben werden, damit sie nicht mehr vorhanden sind benötigen Sie einen Sicherungsspeicher und nehmen Sie keinen Speicherplatz auf oder belasten Sie die Seite Zuweisungsstrukturen.
Tatsächlich sollte die LOH auf einem 64-Byte-System wesentlich schneller sein und weniger ressourcenintensiv als die normen, da keine objekte vorhanden sind jemals kopiert und alle Objekte erhalten eine ganzzahlige Anzahl von Seiten. im Gegensatz zu den Regulsr Heap Fragmentierung ist nicht wirklich ein Problem, da dies wird für Sie von den hardwaregestützten Seitentabellen gehandhabt. In der Tat könnte es Optimal sein, die LOH niemals zu GC zu zählen, bis die Grenzen des virtuellen Speichers erreicht sind.
Wahrhaftig, eine solche Strategie würde am Ende große Teile Ihres LOH ausschreiben auf die Festplatte, aber das geschieht in einem zweiten gleichzeitigen Prozess. So lange wie Sie ordnen Objekte in der LOH nicht zu und beschmutzen ihre Seiten nicht schneller als Ihre Festplatte sie schreiben kann, sollten Sie keine Verlangsamung sehen außer einer kleinen Konkurrenz für Disk-IO und eine kleine Auswirkung von größerem OS Seitenkarten. Das System wird nicht durchdrehen, weil die meisten dieser Seiten wirklich sind sind frei und werden somit nie wieder von der Platte zurückgelesen. Ohne einen GC Markieren von Objekten in der LOH tritt kein falscher Seitenzugriff durch den GC auf.So Der vom Seitencache verwendete LIFO-Algorithmus ist ein ziemlich anständiger GC das tauscht GC-Overhead für einige Festplattenschreibvorgänge und (gelegentlich) gelegentlich lesen.
Ich denke, es wäre besser, die GC-Metadaten und alle eingebetteten zu halten Zeiger für Objekte in der LOH auf einer separaten Seite vom Rest von die Daten (es kann vorangehen, wenn Sie wollen und der Rest der Seite kann für andere Heaps / Metadaten verwendet werden, damit der GC die Seiten weiterhin freigibt in der LOH, ohne dass unnötige Seitenladungen ausgelöst werden. Seit Objekten in der LOH haben wenige, wenn überhaupt Zeigerelemente / Elemente (oder sind alle Zeiger und muss sowieso vom GC gescannt werden) kann man diese trennen von den Daten und das Beste aus beiden Welten: keine Festplatte schreibt und nein falsche Seite lädt für den GC.
Update : Es sei eine Annahme , dass es LOH-Fragmentierung gibt. Die Frage bezieht sich auf die Auswirkungen der Fragmentierung des Speicheradressraums auf den tatsächlichen Speicher auf x64-Plattformen und auf die Funktionsweise in 32-Bit-Prozessen, die auf x64 ausgeführt werden.
Es geht nicht darum, wie man es vermeidet / umgeht und welche Datenstrukturen zu verwenden sind (der Artikel diskutiert das). Ich habe viele Tests durchgeführt, um herauszufinden, dass verschachtelte sortierte Listen fünfmal schneller sind als unveränderliche Strukturen und komprimiere meine Daten um ca. 40%, indem ich das Schlüssel-Delta in der inneren Liste (uint16 vs int64) und die IntMap / AVL-Struktur verwende Nimm 70/50 Bytes Overhead pro Schlüssel / Wert-Paar. Mit sehr realistischen 10mn Paaren bevorzuge ich verschachtelte SL. Die erwartete / mögliche LOH-Fragmentierung ist also der Preis für Geschwindigkeit und naive Speicherkompression. Ich kann noch nicht im vollen Maßstab testen, wie viel Speicher aufgrund von Fragmentierung tatsächlich "leckt", aber aus dem, was ich gelesen habe, habe ich Gründe zu bezweifeln, dass es irgendwelche Lecks gibt.
Es gibt kein schlechtes Design auf dem Garbage Collector in der CLR. Das Problem besteht darin, dass Sie, um die LOH zu defragmentieren, Platz schaffen und dann die Objekte neu anordnen und verdichten müssen. Bei großen Objekten könnte eine Neuordnung mehrere große Objekte für sehr wenig Speichergewinn bewegen (wenn Sie beispielsweise 100 Objekte mit jeweils 0,5 MB Größe angegeben hätten, müssten Sie möglicherweise 200 MB Arbeitsspeicher kopieren und neu anordnen, um dies zu verdichten Speicherplatz Es gibt eine gute Erklärung für dieses Phänomen unter diesem Link
Die 64-Bit-CLR hat die gleiche Größenschwelle für die LOH (da diese basierend auf realen Anwendungen gewählt wurde) und es wird kein Problem mehr sein als in der 32-Bit-CLR. Was hilft, wenn Sie zu .NET 4.0+ wechseln, das Verbesserungen an den LOH-Algorithmen vorgenommen hat, um Speichermangel zu vermeiden und die Wiederverwendung von Löchern im Stapel zu verbessern. .Net 4.5 hat sogar eine Verdichtung der LOH LOH-Komprimierung MSDN , die die meisten Probleme mit benutzerdefinierten Anwendungen, die sich mit großen Arrays befassen, negieren würde.
Sie werden einen Vorteil mit 64bit haben, einfach wegen der Größe des Adressraums. Nichts von dieser Diskussion negiert jedoch ein Qualitätsdesign Ihrer Software. Der Garbage Collector ist ein Aspekt der Anwendung, der dafür verantwortlich sein kann, dass er langsam ausgeführt wird. Sie sollten sich Ihre Algorithmen und Datenstrukturen ansehen, um sicherzustellen, dass Sie die gewünschten Effizienzgewinne erhalten. Wenn Sie sich den Grenzen Ihrer App nähern und Probleme mit der Fragmentierung feststellen, sollten Sie möglicherweise andere Auflistungen als Arrays verwenden und / oder die Größe Ihrer Arrays beschränken, damit sie nicht auf dem LOH zugewiesen werden.
Messen Sie dann optimieren Sie:)
Tags und Links .net c# memory-management