这是在x64计算机上运行的.NET v4 Windows服务应用程序。在经过几天稳定运行后的某些时候,Windows服务内存消耗会像疯了一样飙升直到它崩溃。我能够以1.2 GB捕获它并捕获内存转储。这是我得到的
如果我在我的转储文件中的windbg中运行!address -summary,我会得到以下结果
!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 GB,另一次显示为242 MB。 (已经回答了。谢谢)
其次,我知道未分类可能意味着托管代码,但是我的堆大小根据!eeheap只有248 MB,实际上匹配242但不接近1.73GB。转储文件大小为1.2 GB,远高于正常情况。我从哪里可以找到使用所有内存的内容。托管堆世界中的任何东西都不到248 MB,但我使用的是1.2 GB。
由于
修改
如果我这样做!堆-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
-------------------------------------------------------------------------------------
答案 0 :(得分:16)
我最近遇到了类似的情况,并发现了一些在调查中有用的技巧。没有一个是银弹,但每个人都对这个问题有了更多的了解。
1)来自SysInternals的vmmap.exe(http://technet.microsoft.com/en-us/sysinternals/dd535533)可以很好地关联本机和托管内存的信息,并在一个漂亮的UI中呈现它。可以使用以下技术收集相同的信息,但这更容易,也是一个不错的起点。遗憾的是,它不适用于转储文件,您需要一个实时进程。
2)“!address -summary”输出是更详细的“!address”输出的汇总。我发现将详细输出放入Excel并运行一些支点很有用。使用这种技术,我发现列为“”的大量字节实际上是MEM_IMAGE页面,可能是加载DLL时加载但随后在数据更改时被复制的数据页面的副本。我也可以过滤到大区域并钻取特定地址。用牙签和大量的祈祷在记忆堆中徘徊是痛苦的,但可以揭示。
3)最后,我在上面做了一个穷人的vmmap.exe技术版本。我加载了转储文件,打开了一个日志,并运行了!地址,!eeheap,!heap和!threads。我还使用!teb定位〜* k中列出的线程环境块。我关闭了日志文件并将其加载到我最喜欢的编辑器中。然后我可以找到一个未分类的块并搜索它是否在一个更详细的命令的输出中弹出。您可以非常快速地将本机和管理堆相关联,以便从您可疑的未分类区域中清除那些。
这些都是手动的。我喜欢编写一个脚本,其输出类似于我在上面的技术3中生成的输出,并输出适合查看vmmap.exe的mmp文件。有一天。
最后一点说明:我在vmmap.exe的输出与!地址输出之间进行了关联,并注意到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
仍然有很多“私人”字节下落不明,但同样,如果我可以将这些字段排除在外,我可以缩小这个问题。
希望这可以为您提供有关如何调查的一些想法。我在同一条船上所以我也很欣赏你所发现的东西。谢谢!
答案 1 :(得分:2)
“使用情况摘要”告诉您有3696个未分类区域,总计17.33 Gb
“最大区域”表示最大的未分类区域为242 Mb。 其余未分类(3695个区域)共同产生的差异高达17.33 Gb。
尝试做一个!heap -s并总结Virt col以查看原生堆的大小,我认为这些也属于非托管桶。 (NB早期版本显示本地堆显式来自!address -summary)
答案 2 :(得分:1)
你最好的选择是在windbg中使用EEHeap和GCHandles命令(http://msdn.microsoft.com/en-us/library/bb190764.aspx)并尝试查看是否可以找到这样泄漏/错误。
不幸的是,由于诊断这些类型的问题几乎总是非常耗时并且在最简单的情况之外需要有人进行全面分析,因此您可能无法得到您正在寻找的确切帮助。在转储上。基本上,不太可能有人能够指出你对Stack溢出的直接回答。大多数人都能够为您指出可能有用的命令。您将不得不进行大量挖掘以找到有关正在发生的事情的更多信息。
答案 3 :(得分:1)
我保留了一份适用于Windows 6.11.1.404的调试工具副本,它似乎能够为“未分类”显示更有意义的内容
使用该版本,我会看到一个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)
答案 4 :(得分:0)
我最近花了一些时间来诊断他们的应用程序在终止之前使用70GB的客户问题(可能是因为达到了IIS应用程序池回收限制,但仍然未经证实)。他们给了我一个35 GB的内存转储。根据我最近的经验,这里有一些关于你提供的内容的观察结果:
在!heap -s输出中,提交列中显示了284 MB的1.247 GB。如果您要在DebugDiag中打开此转储,它会告诉您堆0x60000具有1 GB的已提交内存。您将累计报告的11个段的提交大小,并发现它们只加起来大约102 MB而不是1GB。太烦人了。
缺少“缺失”记忆。它实际上在!heap -s输出中暗示为“Virtual block:”行。不幸的是,!heap -s糟透了,并没有正确显示结束地址,因此报告大小为0.检查以下命令的输出:
!address 17e0000
!address 45bd0000
!address 6fff0000
它将报告正确的结束地址,因此会报告准确的“区域大小”。更好的是,它提供了区域大小的简洁版本。如果将这3个区域的大小添加到102 MB,则应该非常接近1 GB。
那么它们里面有什么?好吧,你可以看看使用dq。通过洞察你可能会发现他们被分配的原因。也许您的托管代码会调用一些具有本机端的第三方代码。
您可以使用!heap 6fff0000 -x -v
找到对堆的引用。如果有参考,您可以再次使用!地址查看他们居住的内存区域。在我的客户问题中,我发现了一个存在于“Usage:Stack”区域的引用。一个“更多信息:”提示引用了堆栈的线程,它碰巧在顶部有一些大的basic_string追加/复制调用。