Как проанализировать <unclassified>использование памяти в windbg - PullRequest
22 голосов
/ 26 января 2012

Это приложение службы Windows .NET v4, работающее на компьютере x64. В какой-то момент после нескольких дней стабильной работы потребление памяти службой Windows резко возрастает, пока не падает. Мне удалось поймать его на 1,2 ГБ и захватить дамп памяти. Вот что я получаю

Если я запускаю! Address -summary в windbg в моем файле дампа, я получаю следующий результат

! Address -summary

--- Usage Summary ------ RgnCount ------- Total Size -------- %ofBusy  %ofTotal
Free                     821      7ff`7e834000 (   7.998 Tb)           99.98%
<unclassified>           3696       0`6eece000 (   1.733 Gb)  85.67%   0.02%
Image                    1851       0`0ea6f000 ( 234.434 Mb)  11.32%   0.00%
Stack                    1881       0`03968000 (  57.406 Mb)  2.77%    0.00%
TEB                      628        0`004e8000 (   4.906 Mb)  0.24%    0.00%
NlsTables                1          0`00023000 ( 140.000 kb)  0.01%    0.00%
ActivationContextData    3          0`00006000 (  24.000 kb)  0.00%    0.00%
CsrSharedMemory          1          0`00005000 (  20.000 kb)  0.00%    0.00%
PEB                      1          0`00001000 (   4.000 kb)  0.00%    0.00%
-
-
-
--- Type Summary (for busy) -- RgnCount ----- Total Size ----- %ofBusy %ofTotal
MEM_PRIVATE                        5837 0`7115a000 (  1.767 Gb)  87.34%  0.02%
MEM_IMAGE                          2185 0`0f131000 (241.191 Mb)  11.64%  0.00%
MEM_MAPPED                           40 0`01531000 ( 21.191 Mb)   1.02%  0.00%
-
-
--- State Summary ------------ RgnCount ------ Total Size ---- %ofBusy %ofTotal
MEM_FREE                            821 7ff`7e834000 (  7.998 Tb)        99.98%
MEM_COMMIT                         6127   0`4fd5e000 (  1.247 Gb) 61.66%  0.02%
MEM_RESERVE                        1935   0`31a5e000 (794.367 Mb) 38.34%  0.01%
-
-
--Protect Summary(for commit)- RgnCount ------ Total Size --- %ofBusy %ofTotal
PAGE_READWRITE                     3412 0`3e862000 (1000.383 Mb) 48.29%   0.01%
PAGE_EXECUTE_READ                   220 0`0b12f000 ( 177.184 Mb)  8.55%   0.00%
PAGE_READONLY                       646 0`02fd0000 (  47.813 Mb)  2.31%   0.00%
PAGE_WRITECOPY                      410 0`01781000 (  23.504 Mb)  1.13%   0.00%
PAGE_READWRITE|PAGE_GUARD          1224 0`012f2000 (  18.945 Mb)  0.91%   0.00%
PAGE_EXECUTE_READWRITE              144 0`007b9000 (   7.723 Mb)  0.37%   0.00%
PAGE_EXECUTE_WRITECOPY               70 0`001cd000 (   1.801 Mb)  0.09%   0.00%
PAGE_EXECUTE                          1 0`00004000 (  16.000 kb)  0.00%   0.00%
-
-
--- Largest Region by Usage ----Base Address -------- Region Size ----------
Free                            0`8fff0000        7fe`59050000 (   7.994 Tb)
<unclassified>                  0`80d92000        0`0f25e000 ( 242.367 Mb)
Image                           fe`f6255000       0`0125a000 (  18.352 Mb)
Stack                           0`014d0000        0`000fc000 (1008.000 kb)
TEB                             0`7ffde000        0`00002000 (   8.000 kb)
NlsTables                       7ff`fffb0000      0`00023000 ( 140.000 kb)
ActivationContextData           0`00030000        0`00004000 (  16.000 kb)
CsrSharedMemory                 0`7efe0000        0`00005000 (  20.000 kb)
PEB                             7ff`fffdd000      0`00001000 (   4.000 kb)

Во-первых, почему неклассифицированные должны отображаться один раз как 1,73 ГБ, а другой - как 242 МБ. (На это ответили. Спасибо)

Во-вторых, я понимаю, что неклассифицированный может означать управляемый код, однако мой размер кучи в соответствии с! Eeheap составляет всего 248 МБ, что на самом деле соответствует 242, но даже не близко к 1,73 ГБ. Размер файла дампа составляет 1,2 ГБ, что намного больше обычного. Куда мне пойти отсюда, чтобы узнать, что использует всю память. Все в мире управляемой кучи меньше 248 МБ, но я использую 1,2 ГБ.

Спасибо

EDIT

Если я это сделаю! Куча -s я получаю следующее

LFH Key                   : 0x000000171fab7f20
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                            (k)     (k)    (k)     (k) length      blocks cont. heap 
-------------------------------------------------------------------------------------
Virtual block: 00000000017e0000 - 00000000017e0000 (size 0000000000000000)
Virtual block: 0000000045bd0000 - 0000000045bd0000 (size 0000000000000000)
Virtual block: 000000006fff0000 - 000000006fff0000 (size 0000000000000000)
0000000000060000 00000002  113024 102028 113024  27343  1542    11    3    1c LFH
    External fragmentation  26 % (1542 free blocks)
0000000000010000 00008000      64      4     64      1     1     1    0    0      
0000000000480000 00001002    3136   1380   3136     20     8     3    0    0  LFH
0000000000640000 00041002     512      8    512      3     1     1    0    0      
0000000000800000 00001002    3136   1412   3136     15     7     3    0    0  LFH
00000000009d0000 00001002    3136   1380   3136     19     7     3    0    0  LFH
00000000008a0000 00041002     512     16    512      3     1     1    0    0      
0000000000630000 00001002    7232   3628   7232     18    53     4    0    0  LFH
0000000000da0000 00041002    1536    856   1536      1     1     2    0    0  LFH
0000000000ef0000 00041002    1536    944   1536      4    12     2    0    0  LFH
00000000034b0000 00001002    1536   1452   1536      6    17     2    0    0  LFH
00000000019c0000 00001002    3136   1396   3136     16     6     3    0    0  LFH
0000000003be0000 00001002    1536   1072   1536      5     7     2    0    3  LFH
0000000003dc0000 00011002     512    220    512    100    60     1    0    2      
0000000002520000 00001002     512      8    512      3     2     1    0    0      
0000000003b60000 00001002  339712 168996 339712 151494   976   116    0   18  LFH
    External fragmentation  89 % (976 free blocks)
    Virtual address fragmentation  50 % (116 uncommited ranges)
0000000003f20000 00001002      64      8     64      3     1     1    0      0      
0000000003d90000 00001002      64      8     64      3     1     1    0      0      
0000000003ee0000 00001002      64     16     64     11     1     1    0      0      
-------------------------------------------------------------------------------------

Ответы [ 5 ]

16 голосов
/ 06 февраля 2012

У меня недавно была очень похожая ситуация, и я нашел пару методов, полезных для расследования.Ни одна из них не является серебряной пулей, но каждая из них проливает немного больше света на проблему.

1) vmmap.exe из SysInternals (http://technet.microsoft.com/en-us/sysinternals/dd535533) хорошо справляется с сопоставлением информации о собственной и управляемой памяти и представляет ее вхороший пользовательский интерфейс. Та же информация может быть собрана с использованием методов, описанных ниже, но это гораздо проще и хорошее место для начала. К сожалению, он не работает с файлами дампа, вам нужен живой процесс.

2) Вывод «! Address -summary» является сводом более подробного вывода «! Address».Я нашел полезным поместить подробный вывод в Excel и запустить несколько опорных точек.Используя эту технику, я обнаружил, что большое количество байтов, которые были перечислены как "", на самом деле были страницами MEM_IMAGE, вероятными копиями страниц данных, которые были загружены при загрузке библиотек DLL, но затем скопированы при изменении данных.Я также мог бы фильтровать в большие регионы и углубляться в конкретные адреса.Бродить по дампу памяти зубочисткой и множеством молитв - это больно, но может показаться показательным.

3) Наконец, я выполнил вышеописанную версию техники vmmap.exe для бедного человека.Я загрузил файл дампа, открыл журнал и запустил! Address,! Eeheap,! Heap и! Threads.Я также нацелился на блоки среды потока, перечисленные в ~ * k, с помощью! Teb.Я закрыл файл журнала и загрузил его в мой любимый редактор.Затем я мог бы найти несекретный блок и выполнить поиск, чтобы увидеть, появился ли он в выходных данных одной из более подробных команд.Вы можете довольно быстро сопоставить собственные и управляемые кучи, чтобы отсеять тех из ваших подозрительных несекретных областей.

Все они слишком ручные.Я хотел бы написать скрипт, который будет принимать вывод, аналогичный тому, который я генерировал в методике 3 выше, и выводить файл mmp, подходящий для просмотра vmmap.exe.Однажды.

Последнее замечание: я сделал корреляцию между выводом vmmap.exe и выводом! Address и отметил эти типы областей, которые vmmap пара идентифицирует из различных источников (аналогично тому, что используют! Heap и! Eeheap) но это! адрес не знал о.То есть это те вещи, которые vmmap.exe помечал, но адрес! Не указывал:

.data
.pdata
.rdata
.text
64-bit thread stack
Domain 1
Domain 1 High Frequency Heap
Domain 1 JIT Code Heap
Domain 1 Low Frequency Heap
Domain 1 Virtual Call Stub
Domain 1 Virtual Call Stub Lookup Heap
Domain 1 Virtual Call Stub Resolve Heap
GC
Large Object Heap
Native heaps
Thread Environment Blocks

Было еще много «закрытых» байтов, не учтенных, но я снова могу сузитьпроблема, если я смогу отсеять их.

Надеюсь, это даст вам некоторые идеи о том, как провести расследование.Я в одной лодке, поэтому я был бы признателен за то, что вы тоже нашли.Спасибо!

2 голосов
/ 27 января 2012

«Сводка использования» говорит о том, что у вас есть 3696 несекретных областей, что дает 17,33 Гб

«Самый большой регион» сообщает, что самый большой из неклассифицированных регионов составляет 242 Мб. Остальные несекретные (3695 регионов) вместе составляют разницу до 17,33 Гб.

Попытайтесь сделать! Heap -s и суммировать столбец Virt, чтобы увидеть размер собственных куч, я думаю, они также попадают в неуправляемую группу. (NB более ранние версии показывают явную кучу явно из! Address -summary)

1 голос
/ 09 февраля 2012

У меня есть копия Debugging Tools для Windows 6.11.1.404, которая, кажется, способна показать что-то более значимое для «неклассифицированного» * ​​1001 *

В этой версии я вижу список адресов TEB, а затем:

0:000> !address -summary
 --------- PEB fffde000 not found ----
 TEB fffdd000 in range fffdb000 fffde000
 TEB fffda000 in range fffd8000 fffdb000
...snip...
 TEB fe01c000 in range fe01a000 fe01d000
 ProcessParametrs 002c15e0 in range 002c0000 003c0000
 Environment 002c0810 in range 002c0000 003c0000
-------------------- Usage SUMMARY --------------------------
    TotSize (      KB)   Pct(Tots) Pct(Busy)   Usage
   41f08000 ( 1080352) : 25.76%    34.88%    : RegionUsageIsVAD
   42ecf000 ( 1096508) : 26.14%    00.00%    : RegionUsageFree
    5c21000 (   94340) : 02.25%    03.05%    : RegionUsageImage
    c900000 (  205824) : 04.91%    06.64%    : RegionUsageStack
          0 (       0) : 00.00%    00.00%    : RegionUsageTeb
   68cf8000 ( 1717216) : 40.94%    55.43%    : RegionUsageHeap
          0 (       0) : 00.00%    00.00%    : RegionUsagePageHeap
          0 (       0) : 00.00%    00.00%    : RegionUsagePeb
          0 (       0) : 00.00%    00.00%    : RegionUsageProcessParametrs
          0 (       0) : 00.00%    00.00%    : RegionUsageEnvironmentBlock
       Tot: ffff0000 (4194240 KB) Busy: bd121000 (3097732 KB)

-------------------- Type SUMMARY --------------------------
    TotSize (      KB)   Pct(Tots)  Usage
   42ecf000 ( 1096508) : 26.14%   : <free>
    5e6e000 (   96696) : 02.31%   : MEM_IMAGE
    28ed000 (   41908) : 01.00%   : MEM_MAPPED
   b49c6000 ( 2959128) : 70.55%   : MEM_PRIVATE

-------------------- State SUMMARY --------------------------
    TotSize (      KB)   Pct(Tots)  Usage
   9b4d1000 ( 2544452) : 60.67%   : MEM_COMMIT
   42ecf000 ( 1096508) : 26.14%   : MEM_FREE
   21c50000 (  553280) : 13.19%   : MEM_RESERVE

Largest free region: Base bc480000 - Size 38e10000 (931904 KB)

С моей "текущей" версией (6.12.2.633) я получаю это из того же дампа. Отмечу две вещи:

Данные кажутся суммой значений HeapAlloc / RegionUsageHeap и VirtualAlloc / RegionUsageIsVAD).

Прекрасная ошибка EFAIL, которая, без сомнения, частично ответственна за недостающие данные!

Я не уверен, как это поможет вам с вашим управляемым кодом, но я думаю, что он действительно отвечает на оригинальный вопрос; -)

0:000> !address -summary


Failed to map Heaps (error 80004005)

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
<unclassified>                         7171          aab21000 (   2.667 Gb)  90.28%   66.68%
Free                                    637          42ecf000 (   1.046 Gb)           26.14%
Stack                                   603           c900000 ( 201.000 Mb)   6.64%    4.91%
Image                                   636           5c21000 (  92.129 Mb)   3.05%    2.25%
TEB                                     201             c9000 ( 804.000 kb)   0.03%    0.02%
ActivationContextData                    14             11000 (  68.000 kb)   0.00%    0.00%
CsrSharedMemory                           1              5000 (  20.000 kb)   0.00%    0.00%

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE                            7921          b49c6000 (   2.822 Gb)  95.53%   70.55%
MEM_IMAGE                               665           5e6e000 (  94.430 Mb)   3.12%    2.31%
MEM_MAPPED                               40           28ed000 (  40.926 Mb)   1.35%    1.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_COMMIT                             5734          9b4d1000 (   2.427 Gb)  82.14%   60.67%
MEM_FREE                                637          42ecf000 (   1.046 Gb)           26.14%
MEM_RESERVE                            2892          21c50000 ( 540.313 Mb)  17.86%   13.19%

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READWRITE                         4805          942bd000 (   2.315 Gb)  78.37%   57.88%
PAGE_READONLY                           215           3cbb000 (  60.730 Mb)   2.01%    1.48%
PAGE_EXECUTE_READ                        78           2477000 (  36.465 Mb)   1.21%    0.89%
PAGE_WRITECOPY                           74            75b000 (   7.355 Mb)   0.24%    0.18%
PAGE_READWRITE|PAGE_GUARD               402            3d6000 (   3.836 Mb)   0.13%    0.09%
PAGE_EXECUTE_READWRITE                   80            3b0000 (   3.688 Mb)   0.12%    0.09%
PAGE_EXECUTE_WRITECOPY                   80            201000 (   2.004 Mb)   0.07%    0.05%

--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
<unclassified>                                786000           17d9000 (  23.848 Mb)
Free                                        bc480000          38e10000 ( 910.063 Mb)
Stack                                        6f90000             fd000 (1012.000 kb)
Image                                        3c3c000            ebe000 (  14.742 Mb)
TEB                                         fdf8f000              1000 (   4.000 kb)
ActivationContextData                         190000              4000 (  16.000 kb)
CsrSharedMemory                             7efe0000              5000 (  20.000 kb)
1 голос
/ 31 января 2012

Лучше всего будет использовать команды EEHeap и GCHandles в windbg (http://msdn.microsoft.com/en-us/library/bb190764.aspx)) и попытаться выяснить, можете ли вы найти то, что может быть утечкой / неправильным.

К сожалению, вы, вероятно, не сможете получить именно ту помощь, которая вам нужна, из-за того, что диагностика этих типов проблем почти всегда занимает очень много времени, и за пределами самых простых случаев требуется, чтобы кто-то сделал полный анализ на свалке. В принципе, вряд ли кто-то сможет указать вам прямой ответ на переполнение стека. В основном люди смогут указывать вам команды, которые могут быть полезны. Вам нужно будет много копать, чтобы узнать больше информации о происходящем.

0 голосов
/ 28 сентября 2016

Недавно я потратил некоторое время на диагностику проблемы клиентов, когда их приложение использовало 70 ГБ перед завершением (вероятно, из-за превышения лимита рециркуляции пула приложений IIS, но все еще не подтверждено). Они отправили мне дамп памяти 35 ГБ. Основываясь на моем недавнем опыте, я могу сделать несколько замечаний относительно того, что вы предоставили:

В выводе! Heap -s в столбце Commit отображается 284 МБ из 1,247 ГБ. Если вы откроете этот дамп в DebugDiag, он скажет, что в куче 0x60000 выделено 1 ГБ выделенной памяти. Вы добавите размер фиксации для 11 представленных сегментов и обнаружите, что они составляют всего около 102 МБ, а не 1 ГБ. Так раздражает.

«Отсутствующая» память не отсутствует. На самом деле это указывается в выводе! Heap -s в виде строк «Виртуальный блок:». К сожалению,! Heap -s отстой и не показывает конечный адрес должным образом и поэтому сообщает размер как 0. Проверьте вывод следующих команд:

!address 17e0000
!address 45bd0000
!address 6fff0000

Он сообщит правильный конечный адрес и, следовательно, точный «Размер региона». Более того, он дает краткую версию размера региона. Если вы добавите размер этих 3 областей к 102 МБ, вы должны быть очень близки к 1 ГБ.

Так что в них? Ну, вы можете посмотреть, используя dq. По правописанию вы можете найти подсказку о том, почему они были выделены. Возможно, ваш управляемый код вызывает какой-то сторонний код, который имеет собственную сторону.

Возможно, вы сможете найти ссылки на вашу кучу, используя !heap 6fff0000 -x -v. Если есть ссылки, вы можете увидеть, в каких областях памяти они живут, снова используя адрес! В моей проблеме с клиентом я обнаружил ссылку на регион с использованием «Использование: стек». Подсказка «More info:» ссылалась на поток стека, который оказался с некоторыми большими вызовами добавления / копирования basic_string вверху.

...