【发布时间】:2015-04-02 19:04:01
【问题描述】:
我们的一些 ASP.Net 应用程序存在问题。我们的一些应用从一开始就要求大量内存作为它们的工作集。
在我们的 2 个 webfarm 服务器(每个 4GB RAM)上运行多个应用程序。我们有一个稳定的环境,大约有 1.2GB 的可用内存。
然后我们添加一个 MVC5 + WebApi v2 + Entity Framework 应用程序,它立即声称 1+gb 作为工作集内存,而实际上只使用了大约 300mb。这会导致其他应用程序抱怨内存不足。
我们已经尝试设置虚拟内存限制和私有内存限制,但没有任何效果。如果我们将其设置为 500mb 左右,该应用仍然使用或多或少相同数量的内存(超过 500),并且似乎不遵守现有的限制。
作为参考,我用一个空的 MVC5 项目(VS2013 模板)对此进行了测试,它已经占用了 300mb 的内存,而只使用了大约 10mb。
将应用设置为 32 位应用似乎对减小工作集的大小有一些影响。
有什么方法可以减小工作集的大小,或者对它的大小进行硬性限制?
编辑: 在使用 Web Api v2 和实体框架的项目使用大量内存的情况下,我的 API 控制器如下所示:
namespace Foo.Api
{
public class BarController : ApiController
{
private FooContext db = new FooContext();
public IQueryable<Bar> GetBar(string bla)
{
return db.Bar.Where(f => f.Category.Equals(bla)).OrderBy(f => f.Year);
}
}
正如他们在我能找到的大多数教程中看到的那样(包括来自微软的教程)。由于 LINQ 延迟加载,此处使用 using 不起作用。如果我在任何地方添加一个 ToList(未测试),它可能会起作用,但这是否有任何其他影响?
编辑2: 如果我这样做,它会起作用
namespace Foo.Api
{
public class BarController : ApiController
{
public List<Bar> GetBar(string bla)
{
using(FooContext db = new FooContext){
return db.Bar.Where(f => f.Category.Equals(bla)).OrderBy(f => f.Year).ToList();
}
}
}
ToList() 对 api 的性能有影响吗? (我知道我不能像使用 IQueryable 那样继续廉价查询)
编辑3: 我注意到它的应用程序的私有工作集相当高。有没有办法限制这个? (不会导致不断循环)
编辑4: 据我所知,我在每个 APIController 上都有一个 Dispose。我的前端只是一些简单的 MVC 控制器,但大部分是 .cshtml 和 javascript (angular) 文件。
我们有另一个应用程序,只是普通的 mvc,有两个模型和一些简单的视图(没有数据库,或其他可能泄露的外部资源),这也消耗了 4-500mb 的内存。如果我对其进行分析,我看不到任何表明内存泄漏的东西,我确实看到实际上只使用了 10 或 20 mb,其余的是未分配的非托管内存(但属于私有内存工作集的一部分,因此由这个应用程序和其他任何人都无法使用)。
【问题讨论】:
-
你还打算用那块内存做什么?如果它是您的 Web 服务器,它应该用于您的 Web 应用程序。它可能有多种原因——测试它是否真的是你的应用程序,在 Amazon EC2 实例上启动一个新的 Hello World 应用程序,如果它发生在那里,那么你知道它是框架而不是你。如果是你,那么你需要分析你的应用程序,看看你是不是 1) 泄漏内存,或者 2) 进行了太多的长期分配。
-
通过声明该内存,它使其他应用程序(在同一服务器上)无法使用它。还有一个使用不同内存的应用程序抱怨,因为所有内存都被占用了。我们只是想限制它可以占用多少虚拟内存,以便其他应用程序在需要时可以使用更多内存。
-
其他应用程序是指另一个网络应用程序吗?或者是其他东西?如果是别的东西,它不需要在那个服务器上,那是你的网络服务器。如果是通过 IIS 的另一个 Web 应用程序;那么我的第一组建议是关键,分析你的代码,确保它不是你的代码(很可能是)。
-
这是另一个通过 IIS 的 Web 应用程序。我们正在分析,我们可以看到大量(如 700mb+)只是为未使用的 .net 保留的内存。我稍后会尝试添加屏幕截图。
-
大多数人误解了记忆图...它们通常并不意味着您认为它们会做什么。应用程序会保留大量内存,但如果未提交,则该内存实际上并未使用。此外,很难真正掌握应用程序使用了多少内存,因为内存通常在进程之间共享,例如 .NET 框架本身。所有应用程序共享一个 DLL 的公共实例。
标签: c# asp.net asp.net-mvc iis asp.net-web-api