Ich arbeite an einer Flüssigkeitssimulation in C#. In jedem Zyklus muss ich die Geschwindigkeit der Flüssigkeit an diskreten Punkten im Raum berechnen. Als Teil dieser Berechnung benötige ich einige zehn Kilobyte für den Scratch-Space, um einige double [] -Arrays zu speichern (die genaue Größe der Arrays hängt von einigen Eingabedaten ab). Die Arrays werden nur für die Dauer der Methode benötigt, die sie verwendet, und es gibt ein paar verschiedene Methoden, die solchen Speicherplatz benötigen.Scratch-Speicher in einer verwalteten Umgebung
Wie ich es zu sehen, gibt es einige unterschiedliche Lösungen für die Kratz Arrays Konstruktion:
Verwendung ‚neuer‘ Speicher aus dem Heap jedes Mal die Methode aufgerufen wird, greifen. Das war es, was ich zuerst gemacht habe, aber es bringt viel Druck auf den Müllsammler, und die paar-ms-Spikes einmal oder zweimal pro Sekunde sind wirklich nervig.
Lassen Sie die Scratch-Arrays beim Aufruf der Methoden als Parameter übergeben. Problem ist, dass dies den Benutzer zwingt, sie zu verwalten, einschließlich der richtigen Größenanpassung, was ein großer Schmerz ist. Und es macht die Verwendung von mehr oder weniger Arbeitsspeicher schwierig, da es die API ändert.
Verwenden Sie stackalloc in einem unsicheren Kontext, um den Arbeitsspeicher dem Programmstapel zuzuordnen. Das würde gut funktionieren, außer dass ich mit/unsafe kompilieren müsste und ständig ungeschützte Blöcke in meinen Code streuen müsste, was ich gerne vermeiden würde.
Geben Sie private Arrays beim Start des Programms einmal vor. Das ist in Ordnung, außer dass ich nicht unbedingt die Größe der Arrays kenne, die ich brauche, bis ich einige der Eingabedaten sehen kann. Und es wird wirklich unordentlich, da Sie den Umfang dieser privaten Variablen nicht auf eine einzige Methode beschränken können, so dass sie den Namensraum ständig verschmutzen. Und es skaliert schlecht, da die Anzahl der Methoden, die Arbeitsspeicher benötigen, zunimmt, da ich viel Speicher zuweise, der nur einen Bruchteil der Zeit verwendet wird.
Erstellen Sie eine Art zentralen Pool und ordnen Sie Arbeitsspeicher-Arrays aus dem Pool zu. Das Hauptproblem dabei ist, dass ich keine einfache Möglichkeit sehe, dynamisch große Arrays aus einem zentralen Pool zu reservieren. Ich könnte einen Start-Offset und eine Länge verwenden und den gesamten Arbeitsspeicher im Wesentlichen ein einzelnes großes Array teilen, aber ich habe viel vorhandenen Code, der double [] s annimmt. Und ich muss vorsichtig sein, um einen solchen Poolfaden sicher zu machen.
...
jemand Erfahrung mit einem ähnlichen Problem Hat? Irgendwelche Ratschläge/Lektionen, um von der Erfahrung anzubieten?
Haben Sie wirklich ein paar Dutzend Kilobytes gemeint? Weil das so eine winzige Menge ist, mache ich mir keine Gedanken über die Speicherverwaltung ... –
Es hört sich nicht nach viel an, aber wenn ich 2000 Zyklen/Sek. Durchführe, sind es plötzlich 60MB/Sek Der GC beginnt zu bemerken. –
@JayLemmon, ich denke, dass Sie sich aus Leistungsgründen um diese Details kümmern, richtig? Wenn Ihr Projekt nicht fertig ist, schlage ich vor, dass Sie die Leistung nicht bis zum Ende kümmern. Siehe diesen Artikel über [vorzeitige Optimierung] (http://c2.com/cgi/wiki?PrematureOptimization). Wenn das Projekt abgeschlossen ist, gibt der Artikel interessante Beobachtungen auch zur __ Optimierung im Allgemeinen. Ich zitiere einen Teil: "Ein weit verbreiteter Irrtum ist, dass optimierter Code notwendigerweise komplizierter ist [...] besserer Code, der oft schneller läuft und weniger Speicher verbraucht [...]". – jay