2009-04-05 8 views
3

Beim Ausführen einer .NET 2.0 WinForms-Anwendung in einer Terminaldienste-Umgebung sehe ich einige unerwartete Ergebnisse, die ich nicht genau erklären kann. Alles, was ich gelesen habe, hat gezeigt, dass JIT-geordnete Assemblys (d. H. Die Verwendung von NGen zum Erzeugen nativer Bilder) dazu führen, dass der gesamte Coderaum in privaten Seiten gespeichert wird, wodurch die Arbeitssatzgröße/der Speicherdruck erhöht wird. Tatsächliche Ergebnisse (die mit Process Explorer, VMMap und WinDbg überprüft wurden) zeigen jedoch, dass sogar die JIT-Baugruppen tatsächlich auf gemeinsam nutzbaren Seiten platziert werden (und tatsächlich geteilt werden, wenn mehrere Instanzen der App ausgeführt werden, selbst unter separaten TS Sitzungen/Benutzer)..NET JIT-Baugruppen in gemeinsam nutzbaren Seiten

Kann jemand erklären, warum dies sein könnte? Dies wird in einer W2K8 Server-Umgebung ausgeführt, weshalb ASLR erklärt, warum ein Mangel an spezifischen Basisadressen für jede Assembly & die resultierende Neubildung keine Probleme verursacht. Die Tatsache, dass es sich hierbei nicht um native PE-Images handelt, sollte jedoch dazu führen, dass der Code für diese Assemblys auf privaten Seiten gespeichert wird.

Dies wurde entdeckt, als wir mit der Untersuchung von NGen begannen, um den Speicherdruck zu reduzieren, aber tatsächlich fanden wir eine größere Arbeitssatzgröße - da die JIT-Baugruppen bereits geteilt wurden.

Die letzte Referenz ich gefunden habe, ist hier, was wiederum von unseren tatsächlichen Feststellungen unterscheidet:

http://blogs.msdn.com/morgan/archive/2009/03/07/developing-net-applications-for-deployment-on-terminal-services-or-citrix.aspx

Edit: ich, dass seit der ersten Veröffentlichung der Frage hinzufügen sollte, mehr Experimente unter Windows Server 2003-Testfelder zeigen offenbar auch, dass JIT-Baugruppen zwischen Prozessen gemeinsam genutzt werden können. Ich bin immer noch ratlos, warum alle Ratschläge, die ich finden kann, darauf hindeuten, dass NGen erforderlich ist, aber all die realen Beweise widersprechen dem. Ich hoffe wirklich, dass die Experten hier etwas Licht werfen können.

Danke!

Bearbeite: Ich habe alle meine .NET/CLR-Bücher entstaubt und mir gehen die Ideen für Suchanfragen aus, um zu versuchen, dieses zu lösen; Wer wird meinen Tag damit verbringen, dieses schreckliche nörgelnde Gefühl von "Ich verstehe nicht, was los ist" zu eliminieren! :)

+0

Abgesehen von soliden Beweisen, dass NGen tatsächlich bei der Speichernutzung helfen würde (und dem vernachlässigbaren Einfluss der Startzeit in unserer Umgebung), haben wir uns entschieden, keine nativen Bilder unserer Assemblies zu erstellen. Ich würde trotzdem gerne wissen, warum wir dieses unerwartete Verhalten sehen! – allgeek

Antwort

4

Ich denke, dass Sie direkt auf Modulseiten schauen. Wenn Sie den JIT-Code eingeben, wird er nicht in Ihrer DLL angezeigt - er wird im Speicher angezeigt, den die Laufzeitumgebung zuweist. Die Modulseiten, die Sie betrachten, sind größtenteils Metadaten und IL, weshalb sie immer noch gemeinsam genutzt werden können.

Als ein Experiment, schrieb ich ein kleines Programm, das 30K statische Methoden generiert und ruft sie auf. Auf meinem System hat die JIT-Version dieses Programms 8,2 MB privaten Speicher, während die NGEN-Version 3,8 hat.

Auch innerhalb Ihrer Modulseiten hilft NGEN beim Speichern. Wenn die Laufzeitumgebung ein NGEN-Image laden kann, muss sie die Metadaten Ihres Moduls nicht lesen, um den Code zu JITEN. Die JIT-Version meiner Testanwendung verwendet 2,3 MB Arbeitssatz. Die NGEN-Version verwendet 32 ​​Kilobyte.

NGEN sollte auch Ihre Startzeit helfen. Die Auswirkung auf die Warmstartzeit kann vernachlässigbar sein, aber die Auswirkung auf die Kaltstartzeit (das Speichern des Lesens all dieser Seiten von der Platte) kann bemerkbar sein.

+0

Danke für die Antwort!Ich werde die Dinge abbrechen und ein paar einfachere Tests machen, aber ich habe nicht die gleichen Ergebnisse gesehen. Und nach dem, was ich gelesen habe (und dem Blogeintrag, auf den ich verwiesen habe), sollte ich wirklich den Unterschied in den Modulseiten sehen. AFAIK, die CLR muss immer noch die Metadaten lesen, um Reflektionen, CAS-Richtlinienüberprüfungen usw. zu unterstützen; NGEN beseitigt das nicht. Da es sich um eine TS-Server-basierte App handelt, die von vielen Benutzern ausgeführt wird, ist die Speichernutzung von entscheidender Bedeutung, während die Kaltstartzeit im Wesentlichen irrelevant ist. – allgeek

+0

Kein Problem! Die Metadatenzugriffe für Reflection und dergleichen sind alle faul - nichts wird eifrig geladen, um diese Szenarien zu unterstützen. Ich verstehe, dass in einem TS-Szenario Speicherauslastung der Schlüsselfaktor ist. Ich ermutige Sie, diesen Artikel zu lesen: http://msdn.microsoft.com/en-us/magazine/cc163610.aspx, wenn Sie nicht haben. Wenn Sie Ihre Modulseiten erneut betrachten, sehen Sie sich die WS-Spalte in vmmap anstelle von size/commited an. WS ist die tatsächliche Seitengröße, in der ich 2,3 MB bis 32 KB sah. Viel Glück! –