设为首页 收藏本站
查看: 1591|回复: 0

[经验分享] Entity Framework的启动速度优化

[复制链接]

尚未签到

发表于 2017-12-29 11:50:46 | 显示全部楼层 |阅读模式
  刚开始的时候没有太在意,但是随着系统的发布,这种初次请求,或者闲置若干时间后第一次请求的漫长等待使得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)。
DSC0000.png

DSC0001.png

  这种方式不受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 加上程序集的路径和名称,即可。
  比如在我的机器上,可以看到如下:
DSC0002.jpg

  经过这一操作,首次访问db的速度终于控制到了500ms以内。
  以上是EF的优化,解决了首次部署之后,第一次访问数据库的问题,对于应用程序放置一会儿,再次请求由于线程池回收导致再次访问变慢的问题,通过设置IIS解决。

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



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

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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-429307-1-1.html 上篇帖子: 【转】WebService 的创建,部署和使用 下篇帖子: ASP.NET Zero
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表