Отладка исчерпания кучи рабочего стола
Сейчас я поддерживаю продукт, который, похоже, потребляет много кучи рабочего стола. Двоичные файлы в основном.net, и все они выполняют сеанс 0 как неинтерактивные процессы (все они являются подпроцессами установленной службы Windows). Итак, насколько мне известно, они не должны потреблять кучи рабочего стола.
У нас в системном журнале было несколько сообщений о событиях с кодом 243, за которым следовало событие с кодом 1000 в журнале приложений с перерывами; исключение в журнале приложения всегда 0xc0000142. В конце концов, один из наших сервисов также упадет с каким-то загадочным (бесполезным) сообщением. К сожалению, нам никогда не удавалось запечатлеть это исключение, но все они, похоже, являются достаточно четкими индикаторами исчерпания кучи рабочего стола.
Я пытаюсь выяснить, что потребляет так много кучи рабочего стола, чтобы я мог найти причину. Но здесь я очень застреваю. Первоначально я планировал установить Desktop Heap Monitor, но после нескольких неудачных попыток заставить его работать, я понял, что он не поддерживается ни на чем после XP. Я где-то читал, что Process Explorer должен предоставлять мне ту же информацию, поэтому мы отслеживали следующие объекты в PE:
- Ручка Количество
- GDI объекты
- ПОЛЬЗОВАТЕЛЬСКИЕ объекты
Значение счетчика обращений при получении сообщения о событии 243 существенно не отличается от того, что было несколько дней назад, когда проблема не возникала, или даже в течение нескольких минут после запуска процесса. И объекты GDI и USER оба равны нулю. Итак, я в недоумении от того, что именно может исчерпать кучу рабочего стола, или, если на то пошло, как отладить его дальше. Я где-то читал, что WeakEventManager может вызвать это время проблемы, но мы все равно не используем это.
Я искал эту штуку до смерти и в Google, и в SO, и пока ничего не нашел. Все, что мне действительно нужно, это определить, какой процесс исчерпывает кучу, или, по крайней мере, какой потребляет больше всего. Если у кого-нибудь есть указания, как это сделать, я буду очень признателен.
1 ответ
Старая ветка, но я думал, что вернусь назад, если кто-то столкнется с этим в будущем. После некоторой отладки мы выяснили, какой из наших процессов вызывал проблему. Я решил присоединить WinDbg к процессу и установить bp на CreateWindowEx и NtDestroyWindow. Конечно же, CreateWindowEx действительно вызывался для создания скрытого окна; из параметров в стеке я смог получить класс этого окна (он всегда был одним и тем же), что помогло расширить область действия.
Со временем я начал замечать, что количество вызовов NtDestroyWindow было меньше, чем количество вызовов CreateWindowEx. Поэтому я ушел из стека вызовов, чтобы посмотреть, что создает окна... был конструктор классов и деструктор (нативный, не управляемый). Казалось, что мы вызывали деструктор не так часто, как вызывали конструктор, поэтому со временем мы пропускали некоторые экземпляры этих классов, и с каждым мы также "пропускали" скрытое окно, которое накапливалось со временем и вызывало проблема исчерпания кучи рабочего стола. Отсюда нам удалось отследить, где экземпляры этого класса не уничтожались, и смогли решить проблему.
Однако, не довольный своей судьбой, мне было любопытно, почему Process Explorer оказался для меня не таким полезным, как я ожидал. Все это время он показывал ноль пользовательских объектов, даже когда я знал, что процесс создает оконные объекты. Затем я понял, что PE может показывать эти данные только для процессов, запущенных в одном сеансе. Итак, мне пришлось запустить его в нулевом сеансе, чтобы отслеживать оконные объекты службы. С небольшой помощью PsExec и постов ниже я смог запустить PE в нулевой сессии и переключиться на нее.
https://superuser.com/questions/426868/interactive-session-0-in-windows-7
Оттуда я действительно мог видеть, что у процесса было более 1000 пользовательских объектов. Я также смог запустить WinSpy и подтвердить свои выводы. Конечно, на этом этапе все это было академическим, но, возможно, это будет кому-то полезно в будущем.