ASP。NET MVC和EF代码首先使用内存

时间:2022-09-18 08:59:32

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

我有一个在ASP中构建的应用程序。NET MVC 3,使用SQL CE进行存储,使用EF CTP 5进行数据访问。

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.

我将这个站点部署到一个共享主机上,结果发现它不断地被回收,因为它正在达到他们在(专用的)应用程序池上设置的100mb的限制。

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

该站点在发布模式下运行时使用了大约110mb的RAM。

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

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

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?

唯一显著的区别是当我完全删除EF时(使用假回购)。这降低了30mb-40mb的内存使用量。一个空白的MVC模板使用了大约20mb,所以我觉得这还不算太糟?

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

是否有“标准”ASP的基准。净MVC应用程序?

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 CTP用户正在使用哪些内存,以及内存分析工具(最好是免费的)的一些建议。

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:

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

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

Many thanks Ben

非常感谢本

2 个解决方案

#1


25  

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

我们确实大大减少了内存占用。与以前的100+mb相比,IIS worker进程现在大约有50mb。

Below are some of the things that helped us:

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

  • 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.
  • 检查基础。确保在发布模式下编译,并在web.config中将编译调试设置为false。这样的事很容易忘记。
  • 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.
  • 使用调试符号进行诊断代码。一个例子就是使用像NHProf这样的工具(是的,我以前也遇到过这种情况)。最简单的方法是将这些代码封装在一个#if调试指令中,以确保它没有编译到应用程序的版本中。
  • 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).
  • 不要忘记SQL。orm使得忽略应用程序如何与数据库对话太容易了。使用SQL Profiler或EFProf/NHProf之类的工具可以向您展示正在发生的事情。在EF的情况下,你可能会觉得有点不舒服,特别是如果你使用了大量的延迟加载。一旦你解决了这个问题,你就可以开始优化了(见下面的点)。
  • 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.
  • 延迟加载很方便,但不应该在MVC视图中使用。这是我们的高内存使用的根本原因之一。由于延迟加载(选择N+1),我们网站的主页创建了59个查询。在为这个页面创建一个特定的viewmodel并急切地加载我们需要的关联之后,我们得到了6个在一半时间内执行的查询。
  • 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.
  • 设计模式是用来指导您的,而不是控制应用程序的开发。我倾向于尽可能采用DDD方法。在本例中,我并不想在域模型中公开外键。但是,由于EF不能像NH那样处理多对一关联(它会发出另一个查询,只是为了获取内存中已有对象的外键),所以我最终在页面上显示了一个附加的查询(每个对象)。在这种情况下,为了提高性能,我决定忍受一点代码味道(包括模型中的FK)。
  • 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.
  • 一个常见的“解决方案”是在性能问题上抛出缓存。在制定缓存策略之前,确定真正的问题是很重要的。我本来可以将输出缓存应用到我们的主页(请参阅下面的说明),但这并不能改变这样一个事实:当缓存过期时,我有59个查询访问我的数据库。

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.

关于输出缓存的注意事项:当ASP。NET MVC首先被发布,我们可以做donut缓存,也就是说,缓存一个特定区域之外的页面。如果页面上有特定于用户的信息,这一事实将使输出缓存变得毫无用处。例如,我们在站点的导航菜单中有一个登录状态。这就意味着我不能对页面使用输出缓存,因为它也会缓存登录状态。

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).

最终,对于如何优化应用程序没有硬性规定。当我们停止使用ORM来构建关联(针对站点的公共部分)并将它们手动加载到viewmodel中时,应用程序性能的最大改进就出现了。我们不能使用EF来急切地加载它们,因为有太多的关联(导致混乱的联合查询)。

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.

我们的标签机制就是一个例子。像BlogPost和Project这样的实体可以被标记。标记和可标记实体具有多对多关系。在我们的示例中,最好检索所有标记并缓存它们。然后我们创建了一个linq投影来缓存可标记实体的关联键(例如ProjectId / TagId)。在为页面创建viewmodel时,我们可以为每个可标记的实体构建标记,而不需要访问数据库。同样,这是特定于我们的应用程序的,但是它在性能和降低内存使用方面取得了巨大的改进。

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

我们一路上使用的一些资源/工具:

  • EFProf - to monitor the queries generated by Entity Framework (free trial available)
  • EFProf -监视实体框架生成的查询(免费试用)
  • ANTS Memory Profiler (free trial available)
  • 蚂蚁记忆分析器(免费试用)
  • Windows performance monitor (perfmon)
  • Windows性能监视器(性能)
  • Tess Ferrandez's blog
  • 苔丝Ferrandez的博客
  • Lots of coffee :)
  • 大量的咖啡:)

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.

虽然我们做了改进,将在托管公司(Arvixe)应用程序池的局限性,我觉得责任感建议的人看着他们的Windows经销商计划,这样的限制是到位(因为Arvixe没有提到这个地方当广告计划)。所以当某样东西看起来好得让人难以置信时(无限x,y,z),它通常是。

#2


0  

The funny thing is, I think they got their estimate from this URL:

有趣的是,我认为他们从这个URL得到了他们的估计:

http://blog.whitesites.com/w3wp-exe-using-too-much-memory-and-resources__633900106668026886_blog.htm

http://blog.whitesites.com/w3wp-exe-using-too-much-memory-and-resources__633900106668026886_blog.htm

P.S. It's great article to check and see if you're doing anything that the guy is describing. (For example caching your pages)

附注:这是一篇很棒的文章,看看你是否在做他描述的事情。(例如缓存页面)

P.S.S. Just checked our system and it's running at 50 megs currently. We're using MVC 2 and EF CTP 4.

p.s.刚刚检查了我们的系统,目前运行速度为50兆。我们使用的是MVC 2和EF CTP 4。

#1


25  

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

我们确实大大减少了内存占用。与以前的100+mb相比,IIS worker进程现在大约有50mb。

Below are some of the things that helped us:

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

  • 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.
  • 检查基础。确保在发布模式下编译,并在web.config中将编译调试设置为false。这样的事很容易忘记。
  • 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.
  • 使用调试符号进行诊断代码。一个例子就是使用像NHProf这样的工具(是的,我以前也遇到过这种情况)。最简单的方法是将这些代码封装在一个#if调试指令中,以确保它没有编译到应用程序的版本中。
  • 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).
  • 不要忘记SQL。orm使得忽略应用程序如何与数据库对话太容易了。使用SQL Profiler或EFProf/NHProf之类的工具可以向您展示正在发生的事情。在EF的情况下,你可能会觉得有点不舒服,特别是如果你使用了大量的延迟加载。一旦你解决了这个问题,你就可以开始优化了(见下面的点)。
  • 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.
  • 延迟加载很方便,但不应该在MVC视图中使用。这是我们的高内存使用的根本原因之一。由于延迟加载(选择N+1),我们网站的主页创建了59个查询。在为这个页面创建一个特定的viewmodel并急切地加载我们需要的关联之后,我们得到了6个在一半时间内执行的查询。
  • 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.
  • 设计模式是用来指导您的,而不是控制应用程序的开发。我倾向于尽可能采用DDD方法。在本例中,我并不想在域模型中公开外键。但是,由于EF不能像NH那样处理多对一关联(它会发出另一个查询,只是为了获取内存中已有对象的外键),所以我最终在页面上显示了一个附加的查询(每个对象)。在这种情况下,为了提高性能,我决定忍受一点代码味道(包括模型中的FK)。
  • 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.
  • 一个常见的“解决方案”是在性能问题上抛出缓存。在制定缓存策略之前,确定真正的问题是很重要的。我本来可以将输出缓存应用到我们的主页(请参阅下面的说明),但这并不能改变这样一个事实:当缓存过期时,我有59个查询访问我的数据库。

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.

关于输出缓存的注意事项:当ASP。NET MVC首先被发布,我们可以做donut缓存,也就是说,缓存一个特定区域之外的页面。如果页面上有特定于用户的信息,这一事实将使输出缓存变得毫无用处。例如,我们在站点的导航菜单中有一个登录状态。这就意味着我不能对页面使用输出缓存,因为它也会缓存登录状态。

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).

最终,对于如何优化应用程序没有硬性规定。当我们停止使用ORM来构建关联(针对站点的公共部分)并将它们手动加载到viewmodel中时,应用程序性能的最大改进就出现了。我们不能使用EF来急切地加载它们,因为有太多的关联(导致混乱的联合查询)。

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.

我们的标签机制就是一个例子。像BlogPost和Project这样的实体可以被标记。标记和可标记实体具有多对多关系。在我们的示例中,最好检索所有标记并缓存它们。然后我们创建了一个linq投影来缓存可标记实体的关联键(例如ProjectId / TagId)。在为页面创建viewmodel时,我们可以为每个可标记的实体构建标记,而不需要访问数据库。同样,这是特定于我们的应用程序的,但是它在性能和降低内存使用方面取得了巨大的改进。

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

我们一路上使用的一些资源/工具:

  • EFProf - to monitor the queries generated by Entity Framework (free trial available)
  • EFProf -监视实体框架生成的查询(免费试用)
  • ANTS Memory Profiler (free trial available)
  • 蚂蚁记忆分析器(免费试用)
  • Windows performance monitor (perfmon)
  • Windows性能监视器(性能)
  • Tess Ferrandez's blog
  • 苔丝Ferrandez的博客
  • Lots of coffee :)
  • 大量的咖啡:)

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.

虽然我们做了改进,将在托管公司(Arvixe)应用程序池的局限性,我觉得责任感建议的人看着他们的Windows经销商计划,这样的限制是到位(因为Arvixe没有提到这个地方当广告计划)。所以当某样东西看起来好得让人难以置信时(无限x,y,z),它通常是。

#2


0  

The funny thing is, I think they got their estimate from this URL:

有趣的是,我认为他们从这个URL得到了他们的估计:

http://blog.whitesites.com/w3wp-exe-using-too-much-memory-and-resources__633900106668026886_blog.htm

http://blog.whitesites.com/w3wp-exe-using-too-much-memory-and-resources__633900106668026886_blog.htm

P.S. It's great article to check and see if you're doing anything that the guy is describing. (For example caching your pages)

附注:这是一篇很棒的文章,看看你是否在做他描述的事情。(例如缓存页面)

P.S.S. Just checked our system and it's running at 50 megs currently. We're using MVC 2 and EF CTP 4.

p.s.刚刚检查了我们的系统,目前运行速度为50兆。我们使用的是MVC 2和EF CTP 4。