Überwachung von Anwendungsdomänenressourcen
Hosts mit der Ressourcenüberwachung für die Anwendungsdomäne (ARM) können die CPU- und Speicherauslastung pro Anwendungsdomäne überwachen. Dies ist nützlich für Hosts wie ASP.NET, die eine Vielzahl von Anwendungsdomänen in einem Prozess mit langer Ausführungsdauer verwenden. Der Host kann die Anwendungsdomäne einer Anwendung entladen, die sich negativ auf die Leistung des gesamten Prozesses auswirkt, jedoch nur, wenn er die problematische Anwendung ermitteln kann. Die ARM stellt Informationen bereit, die als Unterstützung bei solchen Entscheidungen herangezogen werden können.
In einem Hostingdienst werden möglicherweise viele Anwendungen auf einem ASP.NET-Server ausgeführt. Wenn eine Anwendung im Prozess zu viele Speicherressourcen verbraucht oder zu viel Prozessorzeit in Anspruch nimmt, kann der Hostingdienst mithilfe der ARM die Anwendungsdomäne ermitteln, die das Problem verursacht.
Die ARM ist für den Einsatz bei aktiven Anwendungen entsprechend einfach konzipiert. Sie können mithilfe der Ereignisablaufverfolgung für Windows (ETW) oder direkt über verwaltete oder native APIs auf die Informationen zugreifen.
Aktivieren der Ressourcenüberwachung
Die ARM kann auf vier Arten aktiviert werden: Durch Bereitstellen einer Konfigurationsdatei beim Starten der Common Language Runtime (CLR), durch eine nicht verwaltete Hosting-API, durch verwalteten Code oder durch Lauschen auf ARM-ETW-Ereignisse.
Sobald die ARM aktiviert ist, beginnt diese mit der Sammlung von Daten für alle Anwendungsdomänen im Prozess. Wenn vor der Aktivierung der ARM eine Anwendungsdomäne erstellt wurde, wird bei der Aktivierung der ARM (nicht bei der Erstellung der Anwendungsdomäne) die Sammlung kumulativer Daten gestartet. Sobald diese aktiviert ist, kann die ARM nicht deaktiviert werden.
Sie können die ARM beim Start der CLR aktivieren, indem Sie das <appDomainResourceMonitoring>-Element zur Konfigurationsdatei hinzufügen und das
enabled
-Attribut auftrue
festlegen. Der Wertfalse
(Standardeinstellung) gibt lediglich an, dass die ARM beim Start nicht aktiviert wurde. Sie können sie später durch eine der anderen Aktivierungsmethoden aktivieren.Der Host kann die ARM durch Anfordern der Hostingschnittstelle ICLRAppDomainResourceMonitor aktivieren. Sobald diese Schnittstelle erfolgreich abgerufen wurde, wird die ARM aktiviert.
Verwalteter Code kann die ARM aktivieren, indem die statische (
Shared
in Visual Basic) AppDomain.MonitoringIsEnabled-Eigenschaft auftrue
festgelegt wird. Sobald die Eigenschaft festgelegt ist, wird die ARM aktiviert.Sie können die ARM nach dem Start durch Lauschen auf ETW-Ereignisse aktivieren. Wenn Sie den öffentlichen Anbieter
Microsoft-Windows-DotNETRuntime
mit dem SchlüsselwortAppDomainResourceManagementKeyword
aktivieren, wird die ARM aktiviert, und sie beginnt mit dem Auslösen von Ereignissen für alle Anwendungsdomänen. Um Daten mit Anwendungsdomänen und -threads zu korrelieren, müssen Sie auch den AnbieterMicrosoft-Windows-DotNETRuntimeRundown
mit dem SchlüsselwortThreadingKeyword
aktivieren.
Verwenden der ARM
Die ARM stellt die gesamte von einer Anwendungsdomäne in Anspruch genommene Prozessorzeit sowie drei Arten von Informationen zur Speicherauslastung bereit.
Gesamtprozessorzeit für eine Anwendungsdomäne in Sekunden: Diese wird durch Addieren der Threadzeiten berechnet, die vom Betriebssystem für alle Threads gemeldet werden, die während ihrer Lebensdauer Zeit für die Ausführung in der Anwendungsdomäne aufgewendet haben. Blockierte Threads oder Threads im Ruhezustand nehmen keine Prozessorzeit in Anspruch. Wenn ein Thread nativen Code aufruft, ist die vom Thread für nativen Code aufgewendete Zeit im Wert für die Anwendungsdomäne enthalten, in der der Aufruf erfolgt ist.
Verwaltete API: Eigenschaft AppDomain.MonitoringTotalProcessorTime
Hosting-API: ICLRAppDomainResourceMonitor::GetCurrentCpuTime-Methode
ETW-Ereignisse: Ereignisse
ThreadCreated
,ThreadAppDomainEnter
undThreadTerminated
. Informationen zu Anbietern und Schlüsselwörtern finden Sie im Artikel CLR-ETW-Ereignisse unter „ETW-Ereignisse der Anwendungsdomänen-Ressourcenüberwachung“.
Gesamtanzahl der durch eine Anwendungsdomäne während ihrer Lebensdauer vorgenommenen verwalteten Zuordnungen in Byte: Die Gesamtanzahl der Zuordnungen spiegelt nicht immer die Speicherauslastung einer Anwendungsdomäne wider, da die zugeordneten Objekte kurzlebig sein können. Wenn eine Anwendung eine große Anzahl von Objekten zuordnet und freigibt, können die Kosten für die Zuordnungen beträchtlich sein.
Verwaltete API: Eigenschaft AppDomain.MonitoringTotalAllocatedMemorySize
Hosting-API: ICLRAppDomainResourceMonitor::GetCurrentAllocated-Methode
ETW-Ereignisse: Ereignis
AppDomainMemAllocated
, FeldAllocated
Verwalteter Speicher in Byte, auf den durch eine Anwendungsdomäne verwiesen wird und der bei der letzten vollständigen blockierenden Collection beibehalten wurde: Dieser Wert ist erst nach einer vollständigen blockierenden Collection präzise. (Dieser Vorgang stellt das Gegenteil zu gleichzeitigen Auflistungen dar, die im Hintergrund ausgeführt werden und die Anwendung nicht blockieren.) Die Methodenüberladung GC.Collect() führt beispielsweise zu einer vollständigen blockierenden Auflistung.
Verwaltete API: Eigenschaft AppDomain.MonitoringSurvivedMemorySize
Hosting-API: ICLRAppDomainResourceMonitor::GetCurrentSurvived-Methode mit dem Parameter
pAppDomainBytesSurvived
ETW-Ereignisse: Ereignis
AppDomainMemSurvived
, FeldSurvived
Gesamter verwalteter Speicher in Byte, auf den vom Prozess verwiesen wird und der bei der letzten vollständigen blockierenden Collection beibehalten wurde: Der Speicher, der für einzelne Anwendungsdomänen beibehalten wird, kann mit dieser Zahl verglichen werden.
Verwaltete API: Eigenschaft AppDomain.MonitoringSurvivedProcessMemorySize
Hosting-API: ICLRAppDomainResourceMonitor::GetCurrentSurvived-Methode mit dem Parameter
pTotalBytesSurvived
ETW-Ereignisse: Ereignis
AppDomainMemSurvived
, FeldProcessSurvived
Ermittlung des Zeitpunkts, an dem eine vollständige blockierende Auflistung auftritt
Um zu ermitteln, wann die Menge des beibehaltenen Speichers genau ist, müssen Sie wissen, wann soeben eine vollständige blockierende Auflistung aufgetreten ist. Die hierbei angewendete Methode hängt von der API ab, die Sie zum Untersuchen der ARM-Statistik verwenden.
Verwaltete API
Wenn Sie die Eigenschaften der AppDomain-Klasse verwenden, können Sie sich mithilfe der GC.RegisterForFullGCNotification-Methode für Benachrichtigungen über vollständige Auflistungen registrieren. Der von Ihnen verwendete Schwellenwert ist nicht von Bedeutung, da Sie auf den Abschluss einer Auflistung warten, nicht auf den Ansatz einer Auflistung. Sie können dann die Methode GC.WaitForFullGCComplete aufrufen, die bis zum Abschluss einer vollständigen Auflistung blockiert ist. Sie können einen Thread erstellen, der die Methode in einer Schleife aufruft und bei der Rückgabe der Methode alle erforderlichen Analysen durchführt.
Alternativ können Sie in regelmäßigen Abständen die GC.CollectionCount-Methode aufrufen, um festzustellen, ob sich die Anzahl der Auflistungen der Generation 2 erhöht hat. Dieses Verfahren kann abhängig von der Abrufhäufigkeit möglicherweise keine genauen Angaben zum Auftreten einer vollständigen Auflistung bereitstellen.
Hosting-API
Wenn Sie die nicht verwaltete Hosting-API verwenden, muss Ihr Host der CLR eine Implementierung der IHostGCManager-Schnittstelle übergeben. Die CLR ruft die Methode IHostGCManager::SuspensionEnding auf, wenn bei der Ausführung einer Auflistung die Ausführung der angehaltenen Threads fortgesetzt wird. Die CLR übergibt die Erzeugung der abgeschlossenen Auflistung als Parameter der Methode, damit der Host ermitteln kann, ob die Auflistung vollständig oder teilweise ausgeführt wurde. Ihre Implementierung der IHostGCManager::SuspensionEnding-Methode kann den beibehaltenen Speicher abfragen, um sicherzustellen, dass die Werte direkt nach ihrer Aktualisierung abgerufen werden.