2011-02-18 117 views
16

我有一个内置在ASP.NET MVC 3中的应用程序,它使用SQL CE存储和EF CTP 5进行数据访问。ASP.NET MVC和EF代码第一次内存使用

我已经将此站点部署到共享主机,只是发现它不断被回收,因为它达到了他们在(专用)应用程序池上设置的100mb限制。

该网站在发布模式下运行时使用大约110MB RAM。

我试过使用SQL Server Express而不是CE,这没什么区别。

唯一的显着差异是当我完全删除EF(使用假回购)。这减少了30mb-40mb之间的内存使用量。一个空白的MVC模板使用大约20mb,所以我认为这不是太糟糕?

“标准”ASP.NET MVC应用程序是否有任何基准?

很高兴知道其他EF CTP用户获得的内存使用情况以及针对内存分析工具(最好是免费的)的一些建议。

值得一提的是我如何处理EF ObjectContext的生命周期。我使用的每个请求的会话和实例的ObjectContext使用StructureMap:

For<IDbContext>().HttpContextScoped().Use(ctx => new MyContext("MyConnStringName")); 

非常感谢 本

+1

海事组织,为您的应用程序池100MB是微不足道的。 – 2011-02-18 18:45:03

+0

这就是我的想法,但直到我有东西来衡量它与我没有真正的情况下回到主机。 – 2011-02-18 19:04:16

+0

这取决于你的支付多少。很明显,每月10美元的共享托管公司不会为这样的经济协议分配更多的资源。另一方面,如果你每月支付50美元左右,你应该得到1GB的内存,这将是很多。 – 2011-02-19 21:04:42

回答

25

我们确实设法相当显着地减少了我们的内存占用量。与之前的100 + MB相比,IIS工作进程现在位于50MB左右。

下面是一些可以帮助我们的东西:

  • 检查的基础知识。确保在发布模式下编译并在web.config中将编译调试设置为false。很容易忘记这样的事情。
  • 使用DEBUG符号来诊断代码。这样做的一个例子就是使用像NHProf这样的工具(是的,我之前被这个问题抓住了)。最简单的方法是将这些代码封装在#if DEBUG指令中,以确保它不会编译到应用程序的发行版中。
  • 不要忘记SQL。 ORM很容易忽略你的应用程序与数据库的对话。使用SQL Profiler或EFProf/NHProf等工具可以准确地告诉你发生了什么。在EF的情况下,你可能会感觉有点不舒服,特别是如果你大量使用延迟加载。一旦你解决了这个问题,你可以开始优化(见下文)。
  • 延迟加载很方便,但不应在MVC视图(IMO)中使用。这是我们高内存使用率的根本原因之一。我们网站的主页由于延迟加载(SELECT N + 1)而创建了59个单独的查询。在为这个页面创建一个特定的视图模型并且急切地加载我们需要的关联之后,我们就完成了一半时间内执行的6个查询。
  • 设计模式可以指导你,而不是规定你的应用程序的开发。我倾向于在可能的情况下遵循DDD方法。在这种情况下,我真的不想在我的域模型上公开外键。然而,由于EF不像NH那样处理多对一的关联(它会发出另一个查询来获取我们已经拥有的对象的外键),所以我最终得到了一个额外的查询(每个对象)显示在我的页面上。在这种情况下,我决定为了提高性能,可以忍受一点代码味道(包括我的模型中的FK)。
  • 一个常见的“解决方案”是在性能问题上抛出缓存。在制定缓存策略之前,确定真正的问题很重要。我本可以将输出缓存应用到我们的主页(请参阅下面的注释),但这并没有改变这个事实,即当缓存过期时,有59个查询会触发我的数据库。

输出缓存的说明: 当ASP.NET MVC首次发布,我们能够做甜甜圈缓存,即从一个特定区域(一个或多个)除了缓存的页面。事实上,这不再可能使输出缓存相当无用,如果你有页面上的用户特定信息。例如,我们在网站的导航菜单中拥有登录状态。仅此一项意味着我无法使用输出缓存作为页面,因为它也会缓存登录状态。

最终,如何优化应用程序并没有硬性规定。当我们停止使用ORM构建我们的关联(面向公众面对我们网站的一部分)并将其手动加载到我们的视图模型中时,我们的应用程序性能得到了最大的改善。我们不能使用EF来加载它们,因为有太多的关联(导致UNION查询混乱)。

一个例子是我们的标记机制。像BlogPost和Project等实体可以被标记。标签和可标记的实体具有多对多的关系。在我们的情况下,最好检索所有标签并缓存它们。然后,我们创建了一个linq投影来缓存可标记实体的关联关键字(例如ProjectId/TagId)。当为我们的页面创建视图模型时,我们可以为每个可标记的实体构建标签而不会触及数据库。同样,这对我们的应用程序是特定的,但它在性能和降低内存使用方面取得了巨大的进步。

一些我们前进的道路上所使用的资源/工具:

虽然我们确实在托管公司的(Arvixe)应用程序池限制下进行了改进,但我确实有责任建议正在查看其Windows经销商计划的人员提供此类限制(因为Arvixe在广告计划时没有提及这一点)。所以当某些东西看起来太好以至于不真实(无限的x,y,z)时,通常是这样。