Получение глобальных корней из .NET Программы
Вопрос
Недавно я начал использовать инструменты профилирования муравьев для производственных работ. Помимо поражения их удивительностью, я не мог не задаться вопросом, как они работают. Например, одна из наиболее полезных функций позволяет визуализировать глобальные корни программы работает в комплекте с количеством ссылок на значения различных типов.
Как этот инструмент получает эту информацию?
Решение
(Полное раскрытие: я нахожусь в команде Visual Studio Profiler, но приведенная ниже информация общедоступна)
Вы можете сделать это, написав Profiler CLR, который работает внутри процесса, который вы нацеливаетесь. Profillers CLR являются объектами C ++ COM, которые создаются при создании времени выполнения, когда COR_PROFILER
и COR_PROFILING_ENABLED
Переменные среды установлены (см. здесь) Есть два основных Интерфейсы профилирования CLR, конкретно, ICorProfilerCallback
и ICorProfilerInfo
. ICorProfilerCallback
Это то, что CLR использует, чтобы уведомить вас о конкретных событиях, которые вы подписываетесь (модульные нагрузки, функционируют затраты JIT, создание потоков, события GC), в то время как ICorProfilerInfo
Может использоваться вашим профилировщиком для получения дополнительной информации о потоках, модулях, типах, методах и метаданных для загруженных сборок. Этот интерфейс - это то, что вы мог Используйте для получения информации о символах о выделенных типах.
С вашим профилировщиком в процессе вы можете протолкнуть GC ICorProfilerInfo::ForceGC
. Анкет После завершения GC ваш профилировщик будет уведомлен через ICorProfilerCallback2::GarbageCollectionFinished
, и вы получите корневые ссылки через ICorProfilerCallback2::RootReferences2
. Анкет Когда вы объединяете корневую справочную информацию с ICorProfilerCallback::ObjectReferences
, вы можете получить полный эталонный график объекта для вашего приложения .NET.
Вы можете получить больше информации в реальном времени, используя ICorProfilerCallback::ObjectAllocated
Обратный вызов, чтобы определить, когда отдельные объекты CLR создаются. Это может быть дорого, хотя, поскольку вы несете хотя бы дополнительный вызов функции для каждого выделенного объекта. Вы можете отслеживать отдельные объекты, сопоставив назначенные CLR ObjectID
на ваш собственный внутренний идентификатор. Ан ObjectID
Для данного объекта является эфемерным указателем, поскольку оно может измениться, как происходит сборки мусора, что может привести к движению объектов во время уплотнения. Этот процесс проиллюстрирован здесь. Анкет Вы можете использовать информацию из ICorProfilerCallback::MovedReferences
Чтобы отслеживать движущиеся объекты.
Чтобы активировать обратные вызовы, упомянутые выше, вам необходимо сообщить API профилирования CLR, что вас интересуют. Вы можете сделать это, указав COR_PRF_MONITOR_GC
и COR_PRF_MONITOR_OBJECT_ALLOCATED
как часть ваших мероприятийных флагов при вызове ICorProfilingInfo::SetEventMask
.
Дэвид Бруман - разработчик на Profiler CLR, а также его блог В целом есть множество отличной информации о профилировании, включая все сумасшедшие ловушки и проблемы, с которыми вы можете столкнуться.
Другие советы
Производители, такие как муравьи, используют «профилирование API», представленные самим CLR, что вполне просто может сказать вам, что происходит внутри CLR. Например, существует API обратный вызов-метод, который возникает, когда объект выделен, удачно назван Objectallocated (). Анкет Точно так же есть события для приведенных способов, когда создаются потоки и т. Д.
Исходный API профилирования называется IcorProfilerCallback. Позже версии называются COREPROFILERCALLBACK2 и COREPROFILERCALLBACK3. Если вы гугтете те имена, вы найдете именно ответы, которые вы ищете. На CodeProject вы можете увидеть практический пример: Создание пользовательского профилировщика .NET
Последнее примечание: API не может использоваться из управляемого кода, такого как C # и VB.NET. Это доступно только от неуправляемого кода, например, например, C или C ++. Таким образом, приложение C # не может использовать эту API для изучения собственного поведения и объектов.