ASP.NET MVC和EF code首先内存使用 [英] ASP.NET MVC and EF Code First Memory Usage

查看:532
本文介绍了ASP.NET MVC和EF code首先内存使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用SQL CE存储和EF CTP 5的数据访问内置的ASP.NET MVC 3的应用程序。

I have an application built in ASP.NET MVC 3 that uses SQL CE for storage and EF CTP 5 for data access.

我已经部署了这个网站到一个共享主机才发现,它一直被回收,因为它是击中他们自己的(专用)应用程序池设置100MB的限制。

I've deployed this site to a shared host only to find that it is constantly being recycled as it's hitting the 100mb limit they set on their (dedicated) application pools.

该网站,在释放模式运行时,周围110MB RAM的使用。

The site, when running in release mode uses around 110mb RAM.

我使用SQL Server防爆preSS,而不是试图CE,这没有什么差别。

I've tried using SQL Server Express rather than CE and this made little difference.

唯一显著的区别是,当我删除EF完全(使用假回购)。这种下降30MB-40MB的内存使用情况。空白MVC模板使用20MB左右,所以我想通这是不是太糟糕了?

The only significant difference is when I removed EF completely (using a fake repo). This dropped the memory usage between 30mb-40mb. A blank MVC template uses around 20mb so I figured this isn't too bad?

是否有标准ASP.NET MVC应用程序的任何基准测试吗?

Are there any benchmarks for "standard" ASP.NET MVC applications?

这将是一件好事知道内存利用率等EF CTP用户越来越并为内存分析工具的一些建议(preferably免费的)。

It would be good to know what memory utilisation other EF CTP users are getting as well as some suggestions for memory profiling tools (preferably free ones).

这是值得一提的,我怎么处理EF ObjectContext中的寿命。我使用的每个请求的会话和实例的ObjectContext使用StructureMap:

It's worth mentioning how I'm handling the lifetime of the EF ObjectContext. I am using session per request and instantiating the ObjectContext using StructureMap:

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

非常感谢

Many thanks Ben

推荐答案

我们还是设法相当显著减少我们的内存占用。 IIS工作进程现在坐在50MB左右相比,100 + MB之前。

We did manage to reduce our memory footprint quite significantly. The IIS worker process now sits around 50mb compared to the 100+mb before.

下面是一些帮助我们的事情:

Below are some of the things that helped us:


  • 检查的基础知识。确保在释放模式,并设置编译调试编译为false在web.config中。人们很容易忘记这样的事情。

  • 诊断code使用调试符号。这方面的一个例子是当使用像NHProf工具(是我一直在这之前抓了出来)是。最简单的就是用#if DEBUG指令来包裹等code,以确保它没有编译到应用程序的发布。

  • 请不要忘记SQL。奥姆斯弄得太容易忽略你的应用程序是如何谈论你的数据库。使用SQL事件探查器或类似EFProf工具/ NHProf可以告诉你究竟是怎么回事。在EF的情况下,你可能会觉得有点生病以后,特别是如果你做显著使用延迟加载。一旦你在这个,你就可以开始优化(见下文点)。

  • 延迟加载是方便,但不应该在MVC次(IMO)的使用。这是我们的高内存使用情况的根本原因之一。我们网站的主页被创建,由于延迟加载59单个查询(SELECT N + 1)。此页面创建特定视图模型,并急切地装载协会之后,我们需要的,我们得到了下来,在一半的时间执行6个查询。

  • 设计模式是那里指引着你,不能排除应用程序的开发。我倾向于尽可能遵循DDD方法。在这种情况下,我真的不希望在我的域模型暴露的外键。然而,由于EF不处理多到一关联相当以及NH(它将发出另一查询只是为了获得一个目的,我们已经在存储器的外键),我结束了一个额外的查询(每个对象)我的网页上显示。在这种情况下,我决定,我可以忍受一点code气味(包括FK在我的模型)用于提高性能的缘故。

  • 一个共同的解决方案是在性能问题抛出缓存。你制定你的缓存策略之前确定的真正的问题是很重要的。我可以只应用于输出缓存我们的主页(参见下面的注释),但我有59个查询打我的数据库时的缓存过期,这并不改变的事实。

  • Check the basics. Make sure you compile in release mode and set compilation debug to false in web.config. It's easy to forget such things.
  • Use DEBUG symbols for diagnostic code. An example of this would be when using tools like NHProf (yes I've been caught out by this before). The easiest thing is to wrap such code in an #if DEBUG directive to ensure it's not compiled into the release of your application.
  • Don't forget about SQL. ORMs make it too easy to ignore how your application is talking to your database. Using SQL Profiler or tools like EFProf/NHProf can show you exactly what is going on. In the case of EF you will probably feel a little ill afterwards, especially if you make significant use of lazy loading. Once you've got over this, you can begin to optimize (see point below).
  • Lazy loading is convenient but shouldn't be used in MVC views (IMO). This was one of the root causes of our high memory usage. The home page of our web site was creating 59 individual queries due to lazy loading (SELECT N+1). After creating a specific viewmodel for this page and eagerly loading the associations we needed we got down to 6 queries that executed in half the time.
  • Design patterns are there to guide you, not rule the development of your application. I tend to follow a DDD approach where possible. In this case I didn't really want to expose foreign keys on my domain model. However since EF does not handle many-to-one associations quite as well as NH (it will issue another query just to get the foreign key of an object we already have in memory), I ended up with an additional query (per object) displayed on my page. In this case I decided that I could put up with a bit of code smell (including the FK in my model) for the sake of improved performance.
  • A common "solution" is to throw caching at performance issues. It's important to identify the real problem before you formulate your caching strategy. I could have just applied output caching to our home page (see note below) but this doesn't change the fact that I have 59 queries hitting my database when the cache expires.

输出缓存的注意事项
当ASP.NET MVC首次发布,我们能够做甜甜圈缓存,即从一个特定的区域(S)除了缓存的页面。事实上,这已不再可能使输出缓存pretty无用的,如果你在页面上用户的具体信息。例如,我们在网站的导航菜单内的登录状态。仅这意味着我不能使用输出缓存的页面,因为它也将缓存登录状态。

A note on output caching: When ASP.NET MVC was first released we were able to do donut caching, that is, caching a page APART from a specific region(s). The fact that this is no longer possible makes output caching pretty useless if you have user specific information on the page. For example, we have a login status within the navigation menu of the site. This alone means I can't use Output caching for the page as it would also cache the login status.

最终没有对如何优化应用程序没有硬性规定。在我们的应用程序性能的最大改进来了,当我们停止使用ORM为建设我们的协会(对我们网站的面向公众的一部分),而是手动加载他们进入我们的ViewModels。我们不能用EF来急切地加载它们因为有太多的关联(导致混乱的UNION查询)。

Ultimately there is no hard and fast rule on how to optimize an application. The biggest improvement in our application's performance came when we stopped using the ORM for building our associations (for the public facing part of our site) and instead loaded them manually into our viewmodels. We couldn't use EF to eagerly load them as there were too many associations (resulting in a messy UNION query).

一个例子是我们的标签机制。喜欢的博文和项目的实体可以被标记。标签和tagable实体有不少一对多的关系。在我们的例子这是更好地获取所有的标签和缓存它们。然后,我们创建了一个LINQ投影缓存关联键为我们tagable实体(例如专案编号/ TAGID)。在创建视图模型为我们的页面,我们可以再建立每个tagable实体标签而无需访问数据库。再次,这是专门针对我们的应用程序,但它产生的性能和降低我们的内存使用量的庞大的改善。

An example was our tagging mechanism. Entities like BlogPost and Project can be tagged. Tags and tagable entities have a many-to-many relationship. In our case it was better to retrieve all tags and cache them. We then created a linq projection to cache the association keys for our tagable entities (e.g. ProjectId / TagId). When creating the viewmodel for our page we could then build up the tags for each tagable entity without hitting the database. Again, this was specific to our application but it yielded a massive improvement in performance and in lowering our memory usage.

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

Some of the resources / tools we used along the way:

  • EFProf - to monitor the queries generated by Entity Framework (free trial available)
  • ANTS Memory Profiler (free trial available)
  • Windows performance monitor (perfmon)
  • Tess Ferrandez's blog
  • Lots of coffee :)

虽然我们没有做,将带我们下的托管公司(Arvixe)应用程序池的限制的改进,我确实觉得责任感告知谁在看他们的Windows经销商计划的人,这样的限制已到位(自广告宣传计划时Arvixe没有提到这一点的任何地方)。所以,当事情看起来好得是真实的(无限制的X,Y,Z),它通常是。

Whilst we did make improvements that would take us under the hosting company's (Arvixe) application pool limits, I do feel a sense of duty to advise people who are looking at their Windows Reseller plans, that such restrictions are in place (since Arvixe do not mention this anywhere when advertising the plan). So when something looks too good to be true (unlimited x,y,z), it usually is.

这篇关于ASP.NET MVC和EF code首先内存使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆