Supervisión de recursos de dominio de aplicación
La supervisión de recursos de dominio de aplicación (ARM) permite a los hosts supervisar el uso de CPU y de memoria por parte del dominio de aplicación. Esto es útil para los hosts como ASP.NET que utilizan varios dominios de aplicación en un proceso de ejecución prolongada. El host puede descargar el dominio de aplicación de una aplicación que afecta negativamente al rendimiento de todo el proceso, pero solo si puede identificar la aplicación problemática. ARM proporciona información que puede usarse para ayudar a tomar estas decisiones.
Por ejemplo, un servicio de hospedaje podría tener muchas aplicaciones que se ejecutan en un servidor ASP.NET. Si una aplicación del proceso empieza a consumir demasiada memoria o demasiado tiempo de procesador, el servicio de hospedaje puede usar ARM para identificar el dominio de aplicación que causa el problema.
ARM es lo bastante ligero para utilizarlo en aplicaciones dinámicas. Puede acceder a la información mediante el uso del Seguimiento de eventos para Windows (ETW) o directamente a través de API administradas o nativas.
Habilitación de la supervisión de recursos
ARM se puede habilitar de cuatro maneras: proporcionando un archivo de configuración cuando se inicia Common Language Runtime (CLR), mediante el uso de API de hospedaje no administradas, mediante código administrado o escuchando los eventos ETW de ARM.
En cuanto se habilita ARM, comienza a recopilar datos en todos los dominios de aplicación del proceso. Si un dominio de aplicación se creó antes de habilitar ARM, los datos acumulativos se inician cuando se habilita ARM, no cuando se creó el dominio de aplicación. Una vez habilitado ARM, no se puede deshabilitar.
Puede habilitar ARM al iniciar el CLR agregando el elemento <appDomainResourceMonitoring> al archivo de configuración y estableciendo el atributo
enabled
entrue
. Un valor defalse
(el valor predeterminado) solo significa que no se habilita ARM durante el inicio; puede activarlo posteriormente mediante uno de los otros mecanismos de activación.El host puede habilitar ARM solicitando la interfaz de hospedaje ICLRAppDomainResourceMonitor. Una vez que esta interfaz se obtiene correctamente, se habilita ARM.
El código administrado puede habilitar ARM estableciendo la propiedad estática AppDomain.MonitoringIsEnabled (
Shared
en Visual Basic) entrue
. En cuanto se establece la propiedad, se habilita ARM.Puede habilitar ARM después del inicio escuchando los eventos ETW. ARM se habilita y comienza a generar eventos para todos los dominios de aplicación cuando se habilita el proveedor público
Microsoft-Windows-DotNETRuntime
mediante el uso de la palabra claveAppDomainResourceManagementKeyword
. Para correlacionar datos con dominios de aplicación y subprocesos, debe habilitar también el proveedorMicrosoft-Windows-DotNETRuntimeRundown
con la palabra claveThreadingKeyword
.
Uso de ARM
ARM proporciona el tiempo de procesador total que un dominio de aplicación usa y tres tipos de información sobre el uso de memoria.
Total de tiempo de procesador para un dominio de aplicación, en segundos: esto se calcula con la suma de los tiempos de los subprocesos notificados por el sistema operativo en todos los subprocesos que dedicaron tiempo a ejecutarse en el dominio de aplicación durante su vigencia. Los subprocesos bloqueados o inactivos no usan tiempo de procesador. Cuando un subproceso llama a código nativo, el tiempo que el subproceso emplea en el código nativo se incluye en el recuento del dominio de aplicación donde se realizó la llamada.
API administrada: propiedad AppDomain.MonitoringTotalProcessorTime.
API de hospedaje: método ICLRAppDomainResourceMonitor::GetCurrentCpuTime.
Eventos ETW: eventos
ThreadCreated
,ThreadAppDomainEnter
yThreadTerminated
. Para obtener información sobre los proveedores y las palabras clave, vea "Eventos de supervisión de recursos de dominio de aplicación" en Eventos ETW de CLR.
Asignaciones administradas totales realizadas por un dominio de aplicación durante su vigencia, en bytes: el total de asignaciones no siempre refleja la memoria que usa un dominio de aplicación, porque los objetos asignados pueden ser de corta duración. Sin embargo, si una aplicación asigna y libera grandes cantidades de objetos, el costo de las asignaciones podría ser significativo.
API administrada: propiedad AppDomain.MonitoringTotalAllocatedMemorySize.
API de hospedaje: método ICLRAppDomainResourceMonitor::GetCurrentAllocated.
Eventos ETW: evento
AppDomainMemAllocated
, campoAllocated
.
Memoria administrada, en bytes, a la que hace referencia un dominio de aplicación y que ha sobrevivido a la colección con bloqueo completo más reciente: este número es preciso solo después de una colección con bloqueo completo. (Esto difiere de las colecciones simultáneas, que se producen en segundo plano y no bloquean la aplicación). Por ejemplo, la sobrecarga del método GC.Collect() genera una colección con bloqueo completo.
API administrada: propiedad AppDomain.MonitoringSurvivedMemorySize.
API de hospedaje: método ICLRAppDomainResourceMonitor::GetCurrentSurvived, parámetro
pAppDomainBytesSurvived
.Eventos ETW: evento
AppDomainMemSurvived
, campoSurvived
.
Total de memoria administrada, en bytes, a la que hace referencia el proceso cuya duración va más allá de la colección con bloqueo completo más reciente: la memoria de duración superior para los dominios de aplicación individuales se puede comparar con este número.
API administrada: propiedad AppDomain.MonitoringSurvivedProcessMemorySize.
API de hospedaje: método ICLRAppDomainResourceMonitor::GetCurrentSurvived, parámetro
pTotalBytesSurvived
.Eventos ETW: evento
AppDomainMemSurvived
, campoProcessSurvived
.
Determinación de la ocurrencia de una colección con bloqueo completo
Para determinar cuándo son precisos los recuentos de memoria de mayor duración, es necesario saber cuándo se produce una colección con bloqueo completo. El método para hacer esto depende de la API que se utiliza para examinar las estadísticas de ARM.
API administrada
Si usa las propiedades de la clase AppDomain, puede usar el método GC.RegisterForFullGCNotification para registrar la notificación de las colecciones completas. El umbral utilizado no es importante, ya que se espera a la finalización de una colección y no al enfoque de una colección. A continuación, puede llamar al método GC.WaitForFullGCComplete, que se bloquea hasta que finaliza una colección completa. Puede crear un subproceso que llame al método en un bucle y que realice cualquier análisis necesario de lo que el método devuelve.
Como alternativa, puede llamar al método GC.CollectionCount periódicamente para ver si ha aumentado el número de colecciones de generación 2. Dependiendo de la frecuencia de sondeo, esta técnica podría no proporcionar una indicación lo suficientemente precisa de la ocurrencia de una colección completa.
API de hospedaje
Si utiliza la API de hospedaje no administrada, el host debe pasar al CLR una implementación de la interfaz IHostGCManager. El CLR llama al método IHostGCManager::SuspensionEnding cuando reanuda la ejecución de los subprocesos suspendidos durante la ocurrencia de una colección. El CLR pasa la generación de la colección completada como un parámetro del método, por lo que el host puede determinar si la colección se completó de forma total o parcial. La implementación del método IHostGCManager::SuspensionEnding puede consultar la memoria de duración superior, a fin de garantizar la recuperación de los recuentos en cuando se actualizan.