为什么ASP.NET坚持非托管内存?

时间:2014-06-20 19:55:40

标签: asp.net memory-management

我有一个ASP.NET 4.0应用程序,多年来在页面数和每日用户数方面一直在增长。有一次,它开始失败,并且#34; HTTP错误503.服务不可用。"几乎每天都在下午12点(峰值加载时间)。重新启动应用程序池会将其修复一两天。

检查系统日志显示应用程序池大约每分钟都被回收一次,在蓝色月亮中一次启动Rapid Fail Protection并停止应用程序池。这是一个典型的场景(为清晰起见缩写):

2014-06-10 07:30:53 5117 4 Information event A worker process with process id of '4060' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit. 
2014-06-10 07:31:53 5117 4 Information event A worker process with process id of '16764' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit.
2014-06-10 07:33:53 5117 4 Information event A worker process with process id of '18632' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit.
2014-06-10 07:34:53 5117 4 Information event A worker process with process id of '49096' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit.
2014-06-10 07:35:53 5117 4 Information event A worker process with process id of '8960' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit. 
2014-06-10 07:36:53 5117 4 Information event A worker process with process id of '31384' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit.
2014-06-10 07:37:53 5117 4 Information event A worker process with process id of '37244' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit.
2014-06-10 07:38:53 5117 4 Information event A worker process with process id of '12864' serving application pool 'slepov-27' has requested a recycle because it reached its private bytes memory limit.
2014-06-10 07:39:11 5002 1 Error event       Application pool 'slepov-27' is being automatically disabled due to a series of failures in the process(es) serving that application pool.                  

禁用快速失败保护不是一个选项,因为该应用程序在共享主机上运行。

我的猜测是,所有这些回收都会触发快速失败保护,并且回收是由于应用池上超出内存限制造成的。内存限制设置为400M(不确定哪个,工作集或提交大小 - 通过电子邮件发送支持)。

我已经开始在一个用户场景中找出我的应用程序的典型内存使用情况。我在我的开发机器上的IIS(7)中运行它,并在任务管理器中查看工作集和提交大小。让我感到惊讶的一件事是:在我打开的每一页上,内存上升了大约3-6兆,而页面本身并没有包含太多代码,只是标记。鉴于该网站大约有100页,超过400M似乎不太可能。

另一个惊喜是实际上做了一些处理的页面(主要是内存计算,没有数据库或Web服务调用)。这些页面的问题在于它们将内存增加了200M并且内存没有被回收。我确信没有任何东西可以保留那个记忆,我用ANTS证实了这一点。 '所有堆中的字节'在页面完成处理后返回但是“私人字节”#39;没有。

为了进一步隔离问题,我已经整理了一个测试应用程序(source code),实际上有两个应用程序,一个控制台和一个asp.net。他们所做的就是让你分配1Gb的内存,然后调用GC.Collect。非常简单。但是控制台和asp.net之间的结果截然不同:

 Working Private  Commit    Run the console app
       6       1       5    About to allocate 1Gb.  Press ENTER to continue ... 
    1082    1076    1082    Allocated 1Gb. Press ENTER to deallocate ... 
    1082    1076    1082    Press ENTER to GC.Collect ... 
      16      10      16    Press ENTER to exit ...

                            Run the ASP.NET app
      36      15     102    New up 1Gb
    1131    1110    1326    GC.Collect
     570     548     764    Wait 10 mins
     570     548     764    New up 1Gb
    1132    1111    1322    GC.Collect
     575     554     764    GC.Collect
     575     554     764    

正如您所看到的那样,控制器应用程序(差不多)会在调用GC.Collect之后恢复其原始内存使用量,同时asp.net应用程序会持续保持超过半个内存。

ANTS screenshot

如本ANTS屏幕截图所示,托管内存(所有堆中的字节数)已释放,但未托管(专用字节)未完全释放。为什么呢?

我已设置< compilation debug =" false" />正如许多消息来源所建议的那样。

我看过这些类似的问题(还有更多):

总结一下,我的主要问题是为什么在GC.Collect之后没有完全释放非托管内存?如果有人能够解释每个新的打开页面逐渐增加内存使用量的话,那就太棒了。感谢。

0 个答案:

没有答案