网站内存泄漏问题追踪--初始访问后,三次查询点击内存使用量达400M
网站是使用dotnet1.1开发的项目。类似的问题在windows2000的iis5和windows2003的iis6上也有相同的表现。
具体的现象是在只有一个用户访问的情况下,打开登录页很慢。登录网站后点击里面几个不同的查询功能,没点一次内存就暴增一次。三次点击后内存已经占用了400M以上。
下图是从打开登录页到三次点击的过程。
关注图中Private Bytes(下文简称PB)、Virtual Bytes(下文简称VB)、# Bytes in all Heaps(下文简称BH)三个指标。(Gen 0 heap size、Gen 1 heap size的曲线暂时不要管它)可以看到三个指标的增长关系,PB是在每次点击后增长的比例都很大,而VB每次也有增长,但是增长幅度比PB小很多。BH在整个过程中基本就没有什么增长。因为BH可以看做是托管程序耗用内存的指标,PB是分配给进程私有内存指标,VB是进程的虚拟内存指标。从上图展现它们之间的增长关系可以得出这样一个结论。网站存在某种内存泄漏,因为三次点击从数据库返回的数据并不可能有400M的大小(要是有网速也太高了)。因为BH在整个过程中的增长比例很小,而PB每次都有大比例的增长,所以可以判断内存泄漏的地方不在托管程序,而应该在非托管中。另外对比PB和VB的增长比例,PB的增长比VB明显得多,因此也能基本排除由碎片导致的内存泄漏。
那是什么导致了内存泄漏呢?
用windbg把IIS进程DUMP了出来,查看了托管部分的内存使用,发现确实如性能分析器给出的一样,因此把精力都集中在非托管的检查中。然后检查了进程的HEAP、CallStack、Virtual Memery、Thread、Moudel等占用的内存,也没有发现内存大量占用的情况。那么剩下的可能就是代码使用了VirtualAllocEx分配内存(进程分配内存的方式之一)。
查阅了不少资料,得知Debug Diagnostics Tool能分析VirtualAllocEx分配内存导致内存泄漏的问题。因此使用它重新dump和分析了该网站的iis进程(微軟的居家除蟲包--Debug Diagnostics Tool使用说明)。分析结果如下:
msdatl3.dll is responsible for 361.00 MBytes worth of outstanding allocations. The following are the top 2 memory consuming functions:
msdatl3!CReservedBlockManager::GetBlock+21: 361.00 MBytes worth of outstanding allocations.
原凶就是这个msdatl3.dll的CReservedBlockManager::GetBlock。每调用一次就分配1M的内存。msdatl3.dll是MDAC(Microsoft Data Access Components)的一个实现文件。
问题的原因找到了,目前还没有找到解决的办法>_<.......待续.....
具体的现象是在只有一个用户访问的情况下,打开登录页很慢。登录网站后点击里面几个不同的查询功能,没点一次内存就暴增一次。三次点击后内存已经占用了400M以上。
下图是从打开登录页到三次点击的过程。
关注图中Private Bytes(下文简称PB)、Virtual Bytes(下文简称VB)、# Bytes in all Heaps(下文简称BH)三个指标。(Gen 0 heap size、Gen 1 heap size的曲线暂时不要管它)可以看到三个指标的增长关系,PB是在每次点击后增长的比例都很大,而VB每次也有增长,但是增长幅度比PB小很多。BH在整个过程中基本就没有什么增长。因为BH可以看做是托管程序耗用内存的指标,PB是分配给进程私有内存指标,VB是进程的虚拟内存指标。从上图展现它们之间的增长关系可以得出这样一个结论。网站存在某种内存泄漏,因为三次点击从数据库返回的数据并不可能有400M的大小(要是有网速也太高了)。因为BH在整个过程中的增长比例很小,而PB每次都有大比例的增长,所以可以判断内存泄漏的地方不在托管程序,而应该在非托管中。另外对比PB和VB的增长比例,PB的增长比VB明显得多,因此也能基本排除由碎片导致的内存泄漏。
那是什么导致了内存泄漏呢?
用windbg把IIS进程DUMP了出来,查看了托管部分的内存使用,发现确实如性能分析器给出的一样,因此把精力都集中在非托管的检查中。然后检查了进程的HEAP、CallStack、Virtual Memery、Thread、Moudel等占用的内存,也没有发现内存大量占用的情况。那么剩下的可能就是代码使用了VirtualAllocEx分配内存(进程分配内存的方式之一)。
查阅了不少资料,得知Debug Diagnostics Tool能分析VirtualAllocEx分配内存导致内存泄漏的问题。因此使用它重新dump和分析了该网站的iis进程(微軟的居家除蟲包--Debug Diagnostics Tool使用说明)。分析结果如下:
msdatl3.dll is responsible for 361.00 MBytes worth of outstanding allocations. The following are the top 2 memory consuming functions:
msdatl3!CReservedBlockManager::GetBlock+21: 361.00 MBytes worth of outstanding allocations.
Function | msdatl3!CReservedBlockManager::GetBlock+21 |
Allocation type | Virtual memory allocation(s) |
Allocation Count | 361 allocation(s) |
Allocation Size | 361.00 MBytes |
Leak Probability | 83% |
原凶就是这个msdatl3.dll的CReservedBlockManager::GetBlock。每调用一次就分配1M的内存。msdatl3.dll是MDAC(Microsoft Data Access Components)的一个实现文件。
问题的原因找到了,目前还没有找到解决的办法>_<.......待续.....