Entity Framework的启动速度优化

刚开始的时候没有太在意,但是随着系统的发布,这种初次请求,或者闲置若干时间后第一次请求的漫长等待使得App的体验很差,很多时候App加载好半天数据都没过来。如果前端没处理好,还会导致App的假死。所以就花了点功夫研究下什么原因导致。

刚开始的时候,还以为是WebService的框架出了问题。后面使用App,通过Fiddler看到了,某次请求db.竟然长达6s中,并且每次导致请求超时都出现在db.访问这一块,这显然不正常。早期,我们访问数据库使用的是原始的ADO.NET 执行SQL语句,如果有参数的话,参数化防止SQL注入,然后基本的增删查,通过批量生成存储过程实现,并在底层框架层记录了每次服务的访问语句和次数,这样便于调优。起初认为这样性能是坠吼的,但是随着规模的扩大,效率太低,所以就切换到了Entity Framework上,通过自动生成实体,然后通过LINQ的方式来实现增删改查,这样效率快很多。

意识到是数据访问的问题之后,开始在查找Entity Framework第一次启动比较慢的问题,然后在网上找了一下,发现很多人都遇到过同样的问题。解决方案也比较成熟,比如Pre-Generated Mapping Views,NGen等等,下面就逐个来说明,其实这些在网上也有很多,我这里记录一下作为自己以后备查。

一、Entity Framework初次启动优化

下面提到的方法,有很多需要Entity Framework版本的支持,所以我们在使用Entity Framework的时候,最好使用最新版本。

Pre-Generated Mapping Views

关于使用EntityFramework的注意事项在Performance Considerations for Entity Framework 这篇文章中有详细介绍,其中生成视图操作耗时比较多,在Entity Framework执行查询或者对数据库进行写操作的时候,必须生成一些映射视图来访问数据库,这些映射视图是一系列对数据库中对象的抽象声明,这些数据同时也是app domain的缓存元数据的一部分,在同一应用程序作用域里面,创建多个数据库访问上下文时可以重用这部分对象。因为在第一次查询的时候,生成映射视图是比较耗时的,所以关于这一点,具体的详细操作可以查看msdn上的Pre-Generated Mapping Views,这篇文章提供了两种预先生成映射视图的方法,一种是在Visual Studio中,通过安装EF Power Tools 插件来生成(以下图片,来自msdn)。

这种方式不受EF的版本限制。

网站还提供了第二种通过代码的方式来预先生成视图,这必须要求EF是6.0及以上版本。这也是博客园这篇文章 来,给Entity Framework热热身所使用的方法。一般的,如果是Web站点,可以放在App_Start中来初始化:

protected void Application_Start(object sender, EventArgs e)
{
    //预热EntityFramework
    using (var dbcontext = new mcccEntities())
    {
        var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
        var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
        mappingCollection.GenerateViews(new List<EdmSchemaError>());
    }
}

经过以上处理,大概程序初次查询db从之前的6s下降到了3s左右。

除了以上优化之外,对于EF6.0及之后的版本,可以使用NGen处理来进一步提高速度。

二、NGen优化

相关优化可以查看这篇文章Improving Startup Performance with NGen (EF6 Onwards),下面这条方法,主要是针对EF6及以上版本的,因为低于这个版本的自带该特性,在这篇文章里说的很清楚“在6.0之前的EF中,EF的运行时核心类库也是.NET框架的一部分,其本地映像在.NET 核心类库加载时自动加载,在6.0及之后的版本,EF整个运行时已经被集成到EntityFramework NuGet包中,本地映像需要使用NGen工具来生成才能达到类似的效果”。

提到这里,首先要说一下NGen这个工具的作用以及为什么能够加快应用程序的启动性能。.NET 框架支持为托管应用或者程序集生成本地映像文件来帮助应用程序更快启动和在一些情况下减少内存占用。在应用程序执行之前,通过将托管代码程序集翻译为包含本地机器指令的文件,能够减少.NET JIT编译器在应用程序启动的时候,生成本地指令代码这一过程,从而能够加快应用程序启动。

使用NGen也很简单

1:以管理员身份启动控制台cmd程序

2:切换到本机.NET 工具目录下:

对于32位机器,通常在%WINDIR%\Microsoft.NET\Framework\v4.0.30319\下

对于64位机器,通常在 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\下

3:然后执行 ngen install 加上程序集的路径和名称,即可。

比如在我的机器上,可以看到如下:

经过这一操作,首次访问db的速度终于控制到了500ms以内。

以上是EF的优化,解决了首次部署之后,第一次访问数据库的问题,对于应用程序放置一会儿,再次请求由于线程池回收导致再次访问变慢的问题,通过设置IIS解决。

三、IIS设置

将服务或者站点部署到IIS上之后,在对应的线程池里有两个地方可以设置,如下图:

  • 空闲超时时间,默认是20分钟,表示在20分钟之类,如果没有请求进来,那么对应的线程就处于闲置状态,这里将其改为0。
  • 例常(Regular)回收时间,这里默认为1740分钟,大概是29个小时(为什么是29而不是24,据说是为了将回收时间的影响减小到最小化,方便调试找到问题,29是24以后的第一个质数),表示大概每隔29个小时,IIS会回收一次应用程序线程池里面的线程。

这样设置之后就可以解决第二个问题。

四、总结

本文简单介绍了优化EntityFramework初次启动速度的方法,以及为防止IIS线程超时闲置,以及例常线程回收导致的初次运行时间过长的解决方法,希望对您解决上述问题有所帮助。

时间: 2024-08-13 23:46:50

Entity Framework的启动速度优化的相关文章

初次开发 ASP.NET vNext 续篇:云优化的概念、Entity Framework 7.0、目前性能还不够好

继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之后, 关于云优化和版本控制: 我本想做一下MAC和LINUX的self-host测试,但是官方说运行环境的MONO版本至少需要3.4.1,我去年买了个表,至本文发布为止,你让我下地狱去找3.4.1吗,硬着头皮用3.4.0搞了一晚上,MAC一直停留在 httpapi.dll出错,Ubuntu Server 12.0.4 是不认其中的几个DLL包,具体哪几个也忘了,过段时间有了稳定版本再

Entity Framework 数据并发访问错误原因分析与系统架构优化

本文主要记录近两天针对项目发生的数据访问问题的分析研究过程与系统架构优化,我喜欢说通俗的白话,高手轻拍 1. 发现问题 系统新模块上线后,使用频率较高,故在实际使用和后期的问题重现测试中,产生了一下系列的数据访问错误 错误是比较常见的错误 2. 分析问题 系统的架构为前端.业务层与数据层三层架构,采用Entity Framework 3.5作为数据处理技术,采用shared context per request模式,参照的是codeplex上的一个示例.示例地址(此文通俗易懂,代码结构也很清晰

Entity Framework 6 预热、启动优化

虽然文章题目是针对EF的,但涉及的内容不仅仅是EF. 场景介绍 目前在做的一个项目,行业门户,项目部分站点按域名划分如下: user.xxx.com:用户登陆注册 owner.xxx.com:个人用户后台 company.xxx.com:企业后台 manage.xxx.com:网站管理 其中user.xxx.com为个人用户及企业用户登陆入口,manage.xxx.com/login为网站管理后台登陆入口. 四个项目都是mvc4+ef6+autofac+automapper. 补充信息: .ne

Entity Framework 实体框架的形成之旅--利用Unity对象依赖注入优化实体框架(2)

在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建了一个简单的基于泛型的仓储模式的框架,例子也呈现了一个实体框架应用的雏形,本篇继续介绍这个主题,继续深化介绍Entity Framework 实体框架的知识,以及持续优化这个仓储模式的实体框架,主要介绍业务逻辑层的构建,以及利用Unity和反射进行动态的对象注册. 1.EDMX文件位置的调整 我们从上篇例子,

Entity Framework优化一:引发了“System.Data.Entity.Core.EntityCommandExecutionException”类型的异常

错误信息: “System.Data.Entity.Core.EntityCommandExecutionException”类型的异常在 EntityFramework.SqlServer.dll 中发生,但未在用户代码中进行处理. 其他信息:执行命令定义时出错.有关详细信息,请参阅内部异常. 跟踪代码找到详细信息: Entity Framework已有打开的与此Command相关联的DataReader,必须首先将它关闭. EF内部是使用DataReader作为资料存取,所以如果没关闭连接就

Entity Framework DbSet&lt;T&gt;之Include方法与IQueryable&lt;T&gt;扩展方法Include的使用

Entity Framework使用Code First方式时,实体之间已经配置好关系,根据实际情况某些情况下需要同时获取导航属性,比如获取商品的同时需要获取分类属性(导航属性),或者基于优化方面考虑等,下面来看一个例子 例子中有会员实体类(Member)与角色实体类(Role),Role与Member的关系是1:n,控制台应用程序代码如下: using System; using System.Collections.Generic; using System.Linq; using Syst

Code First Entity Framework 6化被动为主动之explicit loading模式实战分析( 附源码)

在使用Entity Framework加载关联实体时,可以有三种方式: 1.懒加载(lazy Loading); 2.贪婪加载(eager loading); 3.显示加载(explicit loading). EF默认使用的是懒加载(lazy Loading).一切由EF自动处理. 这种方式会导致应用程序多次连接数据库,这种情况推荐在数据量较大的情况下使用.当我们需要加载数据较少时,一次性全部加载数据会相对更高效. 我们来看看EF的显示加载(explicit loading)如何让我们完全掌控

《Entity Framework 6 Recipes》中文翻译系列 目录篇 -持续更新

为了方便大家的阅读和学习,也是响应网友的建议,在这里为这个系列做一个目录.在目录开始这前,我先来回答之前遇到的几个问题. 1.为什么要学习EF? 这个问题很简单,项目需要.这不像学校,没人强迫你学习! 我学习EF的原因主要是: a.EF是微软推荐的数据库访问技术: b.能提高我的开发效率,我不喜欢写那密密麻麻的SQL: c.比我写的SQL更合理,更快.目前EF生成的SQL的质量已经很高了.你比较熟悉SQL的话,那它在速度上肯定比不上你,新手的话就别跟我争快慢了,能写一像样的SQL就不错了.至少我

Entity Framework 6.X实现记录执行的SQL功能

Entity Framework在使用时,很多时间操纵的是Model,并没有写sql语句,有时候为了调试或优化等,又需要追踪Entity framework自动生成的sql(最好还能记录起来,方便出错时排查) 方式一: 通过System.Data.Entity.DataBase.Log属性指定一个无返回值的委托,来实现记录日志的功能 public partial class EFContext<T> : DbContext where T : class { public EFContext(