BuildManager

时间:2016-08-05 21:09:28

标签: asp.net-web-api memory-leaks out-of-memory asp.net-web-api2

我有一个预编译的Web应用程序(32位),其中内存使用量缓慢上升,直到我获得OutOfMemoryExceptions。使用分析器,我发现主要嫌疑人是System.Web.VirtualPath对象中的字符串,而这些对象又存储在System.Web.Compilation.BuildManager对象的_localResourcesAssemblies Hashtable中。

这些条目似乎分批添加大约50 MB,每4-6小时一次。我被卡住了 - 我不知道是什么调用BuildManager来添加这些条目。查看条目,它们包含与属性路由控制器(或有效路径路径的父路径)的有效路由匹配的路径。

应用程序目录中不应更改任何文件。

我设置了一个类似路线的简单网络应用,看看我是否可以重现问题,但我还没有能够在测试应用中重现问题。

关于如何找到调用BuildManager(密封类,可能是单例)对象的任何想法?

1 个答案:

答案 0 :(得分:0)

解决方法:删除Microsoft.AspNet.WebPages nuget包(以及依赖它的页面,包括Microsoft.AspNet.WebApi.HelpPage包)。

我们终于得到了一个堆栈跟踪,内存不足来自问题的真正原因(我们的大多数跟踪都在我们自己的代码中,我们一次分配几个MB)。堆栈跟踪发布在下面。

我们能够发现WebPages HTTP模块被动态添加并注册回调,该回调将每个url路径添加到BuildManager中的缓存中,并且由于我们的32位内存空间和大量独特路径,这最终会让我们失去记忆。

正如所承诺的那样,堆栈跟踪最终能够引导我们解决问题:

Exception type: OutOfMemoryException 
Exception message: Exception of type 'System.OutOfMemoryException' was thrown.
 at System.Collections.Hashtable.rehash(Int32 newsize, Boolean forceNewHashCode)
 at System.Collections.Hashtable.expand()
 at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
 at System.Collections.Hashtable.set_Item(Object key, Object value)
 at System.Web.Compilation.BuildManager.EnsureFirstTimeDirectoryInit(VirtualPath virtualDir)
 at System.Web.Compilation.BuildManager.GetBuildResultFromCacheInternal(String cacheKey, Boolean keyFromVPP, VirtualPath virtualPath, Int64 hashCode, Boolean ensureIsUpToDate)
 at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate)
 at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
 at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
 at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
 at System.Web.Compilation.BuildManager.GetObjectFactory(String virtualPath, Boolean throwIfNotFound)
 at System.Web.WebPages.BuildManagerWrapper.GetObjectFactory(String virtualPath)
 at System.Web.WebPages.BuildManagerWrapper.ExistsInPrecompiledSite(String virtualPath)
 at System.Web.WebPages.BuildManagerWrapper.Exists(String virtualPath)
 at System.Web.WebPages.VirtualPathFactoryManager.Exists(String virtualPath)
 at System.Web.WebPages.DefaultDisplayMode.GetDisplayInfo(HttpContextBase httpContext, String virtualPath, Func`2 virtualPathExists)
 at System.Web.WebPages.DisplayModeProvider.GetDisplayInfoForVirtualPath(String virtualPath, HttpContextBase httpContext, Func`2 virtualPathExists, IDisplayMode currentDisplayMode, Boolean requireConsistentDisplayMode)
 at System.Web.WebPages.DisplayModeProvider.GetDisplayInfoForVirtualPath(String virtualPath, HttpContextBase httpContext, Func`2 virtualPathExists, IDisplayMode currentDisplayMode)
 at System.Web.WebPages.WebPageRoute.GetRouteLevelMatch(String pathValue, String[] supportedExtensions, Func`2 virtualPathExists, HttpContextBase context, DisplayModeProvider displayModeProvider)
 at System.Web.WebPages.WebPageRoute.MatchDefaultFiles(String pathValue, String[] supportedExtensions, Func`2 virtualPathExists, HttpContextBase context, DisplayModeProvider displayModes, String currentLevel)
 at System.Web.WebPages.WebPageRoute.MatchRequest(String pathValue, String[] supportedExtensions, Func`2 virtualPathExists, HttpContextBase context, DisplayModeProvider displayModes)
 at System.Web.WebPages.WebPageRoute.DoPostResolveRequestCache(HttpContextBase context)
 at System.Web.WebPages.WebPageHttpModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e)
 at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
 at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)