Отслеживание ресурсов домена приложения
Функция наблюдения за ресурсами доменов приложений (ARM) позволяет узлам отслеживать загрузку ЦП и использование памяти доменом приложения. Это полезно для некоторых узлов, таких как ASP.NET, которые используют несколько доменов приложений в длительных процессах. Узел может выгрузить домен приложения, если его работа понижает производительность процесса в целом. Но для нужно определить проблемное приложение. ARM предоставляет сведения, которые помогут решить эту задачу.
Например, на сервере ASP.NET службы размещения может выполняться несколько приложений. Если одно из приложений процесса потребляет слишком много памяти или процессорного времени, служба размещения с помощью ARM может определить проблемный домен приложения.
Функция ARM достаточно нетребовательна к ресурсам, что позволяет применять ее в работающих приложениях. Нужную информацию можно получить с помощью трассировки событий для Windows (ETW), а также управляемых или собственных интерфейсов API.
Включение наблюдения за ресурсами
ARM можно включить четырьмя способами: в файле конфигурации при запуске общеязыковой среды выполнения (CLR), через неуправляемый интерфейс API размещения, в управляемом коде или ожидая передачи событий трассировки событий Windows ARM.
Сразу после включения ARM начинает сбор данных всех доменов приложений в процессе. Если домен приложения создан до включения ARM, данные накапливаются лишь с момента включения ARM, но не с момента создания домена приложения. После включения ARM отключить нельзя.
Вы можете включить ARM при запуске СРЕДЫ CLR, добавив элемент appDomainResourceMonitoring> в файл конфигурации и задав атрибут
true
.enabled
< Значениеfalse
(по умолчанию) просто означает, что ARM не включается автоматически при запуске. ARM можно включить позже с помощью любого другого механизма активации.Узел может включить ARM, подав запрос на интерфейс размещения ICLRAppDomainResourceMonitor. ARM включается после успешного получения этого интерфейса.
Чтобы включить ARM из управляемого кода, задайте для статического свойства AppDomain.MonitoringIsEnabled (
Shared
в Visual Basic) значениеtrue
. ARM включается сразу после изменения этого свойства.Чтобы включить ARM после запуска, используйте ожидание передачи данных от функции трассировки событий Windows. ARM включается и начинает создавать события для всех доменов приложений при активации общего поставщика
Microsoft-Windows-DotNETRuntime
с помощью ключевого словаAppDomainResourceManagementKeyword
. Чтобы связать данные с потоками и доменами приложений, также нужно включить поставщикMicrosoft-Windows-DotNETRuntimeRundown
с помощью ключевого словаThreadingKeyword
.
Использование ARM
ARM передает данные общего процессорного времени, используемого доменом приложения, а также три параметра использования памяти.
Общее процессорное время для домена приложения, в секундах. Результат вычисляется путем сложения значений времени для всех потоков операционной системы, выполнявшихся в домене приложения за весь период его существования. Заблокированные потоки и потоки в спящем режиме не используют процессорное время. Если поток вызывает машинный код, время нового потока в машинном коде включается в статистику по домену приложения, из которого он был вызван.
Управляемый интерфейс API: свойство AppDomain.MonitoringTotalProcessorTime.
Интерфейс API размещения: метод ICLRAppDomainResourceMonitor::GetCurrentCpuTime.
События трассировки событий Windows: события
ThreadCreated
,ThreadAppDomainEnter
иThreadTerminated
. Сведения о поставщиках и ключевые слова вы найдете в разделе о событиях ресурсов для доменов приложения в статье События трассировки событий Windows в среде CLR.
Общий объем выделенной управляемой памяти для домена приложения за все время его существования (в байтах). Общий объем выделенной памяти не всегда правильно отражает использование памяти доменом приложения, так как объекты могут выделяться на короткий промежуток времени. Но накладные расходы могут оказаться существенными, если приложение часто выделяет и освобождает большое количество объектов.
Управляемый интерфейс API: свойство AppDomain.MonitoringTotalAllocatedMemorySize.
Интерфейс API размещения: метод ICLRAppDomainResourceMonitor::GetCurrentAllocated.
События трассировки событий Windows: событие
AppDomainMemAllocated
, полеAllocated
.
Управляемая память (в байтах), которая используется доменом приложения и осталась выделенной после последней полной блокирующей сборки мусора. Этот параметр имеет смысл, только если выполнялась полная блокирующая сборка (Это отличается от параллельных коллекций, которые происходят в фоновом режиме и не блокируют приложение.) Например, перегрузка GC.Collect() метода вызывает полную блокировку коллекции.
Управляемый интерфейс API: свойство AppDomain.MonitoringSurvivedMemorySize.
Интерфейс API размещения: метод ICLRAppDomainResourceMonitor::GetCurrentSurvived, параметр
pAppDomainBytesSurvived
.События трассировки событий Windows: событие
AppDomainMemSurvived
, полеSurvived
.
Общий объем управляемой памяти (в байтах), которая используется процессом и осталась выделенной после последней полной блокирующей сборки мусора. Это значение можно сравнить с объемами памяти, которая осталась выделенной для отдельных доменов приложений.
Управляемый интерфейс API: свойство AppDomain.MonitoringSurvivedProcessMemorySize.
Интерфейс API размещения: метод ICLRAppDomainResourceMonitor::GetCurrentSurvived, параметр
pTotalBytesSurvived
.События трассировки событий Windows: событие
AppDomainMemSurvived
, полеProcessSurvived
.
Как определить время полной блокирующей сборки мусора
Чтобы определить точность сведений об оставшемся объеме памяти, нужно узнать время последней полной блокирующей сборки. Метод определения времени зависит от того, какой API-интерфейс вы используете для изучения статистики ARM.
Управляемый интерфейс API
Если вы используете свойства класса AppDomain, метод GC.RegisterForFullGCNotification позволяет зарегистрироваться для получения уведомлений о полных сборках. Указываемое здесь пороговое значение не играет роли, так как вас интересует только завершение сборки, а не ее приближение. После этого вызовите метод GC.WaitForFullGCComplete, который блокируется до завершения полной сборки. Вы можете создать отдельный поток, который вызывает этот метод в цикле и проводит анализ данных при каждом завершении метода.
Кроме того, вы можете периодически вызвать метод GC.CollectionCount, чтобы отслеживать увеличение количества сборок для поколения 2. В зависимости от частоты опроса такой подход не всегда будет давать точные сведения о времени выполнения полной сборки мусора.
Интерфейс API размещения
Если вы используете API размещения, а не управляемый API, узел должен передать в среду CLR реализацию интерфейса IHostGCManager. Среда CLR вызывает метод IHostGCManager::SuspensionEnding из этого интерфейса, когда возобновляет выполнение потоков, приостановленных на время сбора мусора. Среда CLR передает в параметре этого метода номер поколения выполненной сборки. Это позволяет узлу определить тип сборки (полная или частичная). Вы можете поместить запросы данных оставшейся памяти в реализацию метода IHostGCManager::SuspensionEnding, чтобы получать их сразу же по мере обновления.