debug实战:Unmanaged High Memory非托管高内存
最近又监控到一个高内存的问题,周五下班把系统打开,周末2天没关,周一来看已经涨到5.2G,这次与以往不同,不是.net的内存泄漏,而是非托管引起的。
1. 抓dump,确定高内存的类型
//dump有5.2G,.net的堆只有191M,可以判断是unmanaged high memory
0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0000000159852b88
generation 1 starts at 0x00000001597d26a0
generation 2 starts at 0x0000000003231000
ephemeral segment allocation context: none
segment begin allocated size
0000000003230000 0000000003231000 000000000dad5f38 0xa8a4f38(176836408)
00000001596b0000 00000001596b1000 0000000159db48f8 0x7038f8(7354616)
Large object heap starts at 0x0000000013231000
segment begin allocated size
0000000013230000 0000000013231000 0000000013906b30 0x6d5b30(7166768)
Total Size: Size: 0xb67e360 (191357792) bytes.
------------------------------
GC Heap Size: Size: 0xb67e360 (191357792) bytes.
2. 用windbg找原因
于是不能用sos ext里的命令了,用CodeProject上的这篇文章里的方法试了一下,如下:
//这个命令能看到所有的内存消耗,确实分配了5G多
0:000> !address -summary
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
*** ERROR: Symbol file could not be found. Defaulted to export symbols for DebussyReverie.dll -
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 412 7fe`897c2000 ( 7.994 Tb) 99.93%
Heap 628 1`24c81000 ( 4.575 Gb) 78.18% 0.06%
<unknown> 1217 0`39381000 ( 915.504 Mb) 15.28% 0.01%
Image 2120 0`14561000 ( 325.379 Mb) 5.43% 0.00%
Stack 200 0`04080000 ( 64.500 Mb) 1.08% 0.00%
Other 13 0`001c6000 ( 1.773 Mb) 0.03% 0.00%
TEB 66 0`00084000 ( 528.000 kb) 0.01% 0.00%
PEB 1 0`00001000 ( 4.000 kb) 0.00% 0.00%
--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE 1509 1`59760000 ( 5.398 Gb) 92.24% 0.07%
MEM_IMAGE 2683 0`184d0000 ( 388.813 Mb) 6.49% 0.00%
MEM_MAPPED 53 0`04bfe000 ( 75.992 Mb) 1.27% 0.00%
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE 412 7fe`897c2000 ( 7.994 Tb) 99.93%
MEM_COMMIT 3267 1`4d29f000 ( 5.206 Gb) 88.96% 0.06%
MEM_RESERVE 978 0`2958f000 ( 661.559 Mb) 11.04% 0.01%
//再查看非托管堆,能看到有1个堆占了4.5G
0:000> !heap -s
LFH Key : 0x000000ff3fbc76ee
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: 0000000002ca0000 - 0000000002ca0000 (size 0000000000000000)
...
000000001fc30000 00001002 4597824 4568704 4597824 568 296 288 0 1 LFH
...
External fragmentation 23 % (59 free blocks)
-------------------------------------------------------------------------------------
//查看有问题的堆,大小为27d1的某个内存块共有6cc72个,27d1*6cc72=10eb24712(4.5G)
0:000> !heap -stat -h 000000001fc30000
heap @ 000000001fc30000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
27d1 6cc72 - 10eb24712 (99.95)
128 18d5 - 1cb648 (0.04)
2740 11 - 29b40 (0.00)
3e80 1 - 3e80 (0.00)
//用size=27d1过滤,查看每个对象的指针UserPtr
0:000> !heap -flt s 27d1
_HEAP @ 90000
...
_HEAP @ 1fc30000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0000000025217420 0281 0000 [00] 0000000025217430 027d1 - (busy)
0000000025219c30 0281 0281 [00] 0000000025219c40 027d1 - (busy)
//随便找个对象地址,看被哪里引用了,悲剧的是,不管找哪个,都没有堆栈信息stack trace!
0:000> !heap -p -a 0000000025217430
address 0000000025217430 found in
_HEAP @ 1fc30000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0000000025217420 0281 0000 [00] 0000000025217430 027d1 - (busy)
3. 用DebugDiag找原因
上面的路目前看起来是走不大通了,于是换Debug大神-美女程序猿-Tess的这篇博文里的方法,改用DebugDiag试试。
- 下载DebugDiag1.2,这是目前最新的版本,已经能支持win7和x64位的系统了。根据你的os选择x86/x64的msi版本并安装。
- 重新启动你的程序,因为这个工具是在跟踪tracking内存分配的过程,所以需要在high memory出现之前就开始监控。
- 打开DebugDiag,选择Add Rule、Native (non-.NET) Memory and Handle,选择要分析的进程,Rule->Status会显示目前处于tracking的状态。
- 执行一段时间、1h 或 1天,转到tab页Processes里右键进程、Create Full Userdump。
- 然后转到Advanced Analysis里选中"Memory Pressure Analyzers"脚本,点击Add Data Files把生成的dump加进去。
- 点击"Start Analysis"就开始分析了,要耐心一点,视dump大小一般需要>10min。
因为要重新启动,下面的dump是我重新抓的,跑了一晚上,大概有1.7G,分析的结果显示是一个DebussyReverie.dll的模块在不停的分配内存。
DebussyReverie.dll is responsible for 1.15 GBytes worth of outstanding allocations. The following are the top 2 memory consuming functions:
DebussyReverie!GetLspGuid+79e: 1.07 GBytes worth of outstanding allocations.
DebussyReverie!GetLspGuid+f31df: 83.04 MBytes worth of outstanding allocations.
Image Name: C:\Program Files\LeagSoft\UniAccess Agent\DebussyReverie.dll
Function DebussyReverie!GetLspGuid+79e
Allocation type Heap allocation(s)
Heap handle 0x00000000`00000000
Allocation Count 114716 allocation(s)
Allocation Size 1.07 GBytes
Leak Probability 81%
//堆栈如下,可惜没能显示从我的代码到问题代码之间的调用关系
Function Source Destination
LeakTrack+13277
DebussyReverie!GetLspGuid+79e
DebussyReverie!GetLspGuid+647
DebussyReverie!GetLspGuid+ea3
DebussyReverie!WSPStartup+431
ws2_32!WahOpenApcHelper+20a
ws2_32!_WSAFDIsSet+e02
ws2_32!WSCInstallProviderAndChains64_32+1971
ws2_32!WSCInstallProviderAndChains64_32+1aa0
ws2_32!WSASendTo+21fc
ws2_32!getsockname+4a
DebussyReverie!PublicService+74b
DebussyReverie!GetLspGuid+a41dd
DebussyReverie!PublicService+2c70
ws2_32!WSApSetPostRoutine+298
ws2_32!WSAConnect+af
System_ni+32f3f2
...
0x7FE8925FEA7
看起来,问题来自公司安装的网络监控软件LeagSoft里的DebussyReverie.dll。大约是下班后服务器断开了,项目里Apache.NMS.ActiveMQ连接出错时调用多线程反复重连,然后被监控软件拦截到后出的错。应该是LeagSoft里的一个Bug,如果能和他们交流一下,应该能进一步确定问题所在,甚至修复这个问题。
debug实战:Unmanaged High Memory非托管高内存的更多相关文章
- debug实战:COM组件GetToSTA导致高内存+GC被阻塞
最近花了好几周解决一个WPF高内存的问题,问题的表象是内存不断增加.未被回收,根源是GC的FinalizeThread被阻塞,导致整个GC挂掉.从以下几步来分析这个问题: 1.用ANTS Memory ...
- C# 托管内存与非托管内存之间的转换
c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存 ...
- C# 中托管内存与非托管内存之间的转换
c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存 ...
- C#+无unsafe的非托管大数组(large unmanaged array in c# without 'unsafe' keyword)
C#+无unsafe的非托管大数组(large unmanaged array in c# without 'unsafe' keyword) +BIT祝威+悄悄在此留下版了个权的信息说: C#申请一 ...
- 非等高cell实战(01)-- 实现微博页面
非等高cell实战(01)-- 实现微博页面 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战来整合一下. 首先看一下效果图: 需求分析 此页面为非等 ...
- 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源
建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...
- 非等高cell实战--实现微博页面
代码地址如下:http://www.demodashi.com/demo/11639.html 前言 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战 ...
- 在VS2010上使用C#调用非托管C++生成的DLL文件
背景 在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使用一些第三方通讯组件的时候,通过C#来开发应用软件时,就需要利用DllImport特性进行方法调用.本篇文章将引导你快速理解这个调用 ...
- C# 托管和非托管混合编程
在非托管模块中实现你比较重要的算法,然后通过 CLR 的平台互操作,来使托管代码调用它,这样程序仍然能够正常工作,但对非托管的本地代码进行反编译,就很困难. 最直接的实现托管与非托管编程的方法就是 ...
随机推荐
- 左 or 右
背景: 掌握的知识:C++.MFC.设计模式.STL,熟悉windows网络编程,了解COM组件但是不精. 近期辞职找工作,发现windows下的C++开发职位很少.linux和移动端开发职位多,但是 ...
- Using Yum Variables
You can use and reference the following built-in variables in yum commands and in all Yum configurat ...
- (顺序表的应用5.4.3)POJ 1012(约瑟夫环问题——保证前k个出队元素为后k个元素)
/* * POJ-1012.cpp * * Created on: 2013年10月31日 * Author: Administrator */ #include <iostream> # ...
- UBIFS 文件系统分析1 - 磁盘结构【转】
转自:http://blog.csdn.net/kickxxx/article/details/7109662 版权声明:本文为博主原创文章,未经博主允许不得转载. ubifs磁盘结构 UBIFS文件 ...
- UICollectionViewDelegateFlowLayout 使用
import UIKit //UICollectionViewLayout //itemSize属性 //设定全局的Cell尺寸,如果想要单独定义某个Cell的尺寸,可以使用下面方法: // - (C ...
- CentOS7安装memcached
三台linux服务器系统CentOS7 一台memcached IP:192.168.155.134 一台Apache IP:192.168.155.130 一台nginx IP:192.168.15 ...
- wf(三)
前言: 到现在我们可以看到,WF4包含一个.xmal 文件的设计器和一个调用活动的runtime.当你创建自己的工作流的时候,你是同时也创建了一个活动, 因为活动是一个继承System.Activit ...
- OpenCV 绘制图像直方图
OpenCV绘制图像直方图,版本2.4.11 直方图可展示图像中的像素分布,是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数.可以借助观察该直方图了解需要如何调整亮度分布.这种直方 ...
- file以及文件大小转化问题
android 获取文件夹.文件的大小 以B.KB.MB.GB 为单位 public class FileSizeUtil { public static final int ...
- sourceforge免费空间申请及使用笔记
sourceforge免费空间申请及使用笔记 sourceforge免费空间安装WordPress博客程序 WordPress博客程序安装文件的上传需要使用工具WinSCP. 你需要在FTP地址填写的 ...