处理EF第一次加载过慢问题

本文转载自:https://www.cnblogs.com/sunShineJing/p/5083184.html

创建mvc web application,采用code first 的方式,MVC5,EF6.0 整了一个网站。开发完之后。直接publish。就这样部署到服务器上了。

在使用过程中发现,网站打开的速度有点慢。而且每隔一段时间不使用,网站的打开速度就变慢。

问题分析:

一开始首先想到的是IIS的应用程序池释放的问题。

后来配置了iis还是过一段时间访问变慢。

后来为了快速解决这个问题,只能先做了一个bat文件,在服务器端模拟一段时间内访问这个网站一下。这样用户在访问的时候不会体会到网站的访问速度变慢的问题。


1

2

3

4

5

6

@echo  正在关掉所有的IE进程(需要设置默认浏览器是IE)

taskkill   /im iexplore.exe /f /t

@echo 正在通过ping来延迟80秒钟,以方便IE打开页面

ping 127.0.0.1 -n 10

@echo 正在访问 http://localhost

start "C:\Program Files\Internet Explorer\iexplore.exe"  http://localhost

这样隔一段时间变慢的问题已经解决了,但是还没有查找到这是什么原因。

后来看到一篇文章说 是因为EF 的原因。

EF方面的原因:

1、Code First第一次启动会对比程序中的Model与数据库表(database initializer ),生成Model与数据库的映射视图

2、随着EF的开源,EF从6开始就不会包含在.net Framework中,安装.net Framework默认是不会安装EF的。因此EF程序集就没有生成本地镜像,这样每次程序启动,EF的代码都会通过just-in-time (JIT) compiler(即时编译器)把MSIL中间代码编译成本机能识别的本地代码。因为这个生成的本地代码存在程序运行的进程里面的内存中,它将回收当程序进程被终止(例如:iis程序池回收,程序池默认是按需触发运行的,没人访问它就不启动了)。由于EF框架还是比较大的,EF6文件大小到4-5M了,所以每次启动都要重写编译本地代码有比较明显的性能影响。

第二、优化方案

我主要是通过以下几方面来优化

一、安装Application Initialization

这是在iis8出来后才有的,iis8内置的功能,而对于iis7.5也提供了一个扩展以支持这个功能。

Application Initialization Module for IIS 7.5

在页面接近底部的地方,找到适合自己架构的安装链接

  • x86 for Windows 7
  • x64 for Windows 7 or Windows Server 2008 R2

安装这个iis模块后,在iis界面中并没有模块图标和配置界面,还需要安装:

http://pan.baidu.com/s/1c091WxM

安装成功之后会多了一个配置如下图:

如果仅配置程序池StartMode为AlwaysRunning还不放心的话, 也可以同时针对站点开启preload和DoAppInitAfterRestart。

设置应用程序池如下图:

设置网站如下图

配置好后,测试了下,效果十分不错。 回收程序池后首次打开各站点,延迟都很低。 其实这个模块的思路和定时从外部触发一个访问是一样的,只是,更好的地方在于,它本身在程序池回收重启的时候就完成了这件事,而不会让外部访问有机会遇到首次访问的情况。

二、用Ngen安装生成EF的本地镜像

1、打开cmd窗口

2、定位到dll所在的目录,如:cd d:\website1\bin,切换到程序的bin目录。

3、运行ngen命令

For 32 bit run:

%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install EntityFramework.SqlServer.dll
For 64 bit run: %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install EntityFramework.SqlServer.dll

注意:这里根据你自己机器(是32还是64)和.net版本,选择相应的命令,只需要安装EntityFramework.SqlServer.dll,因为安依赖EntityFramework.dll,会自动安装生成EntityFramework.dll的本地镜像。

三、禁用第一次ef查询对表__MigrationHistory的问题

使用了ef的Code first会在第一次ef查询的时候会对__MigrationHistory访问,是为了检查数据库和model是否匹配,以保证ef能正常运行。通过监测会先执行下面的sql:

  1. SELECT
  2. [GroupBy1].[A1] AS [C1]
  3. FROM ( SELECT
  4. COUNT(1) AS [A1]
  5. FROM [dbo].[__MigrationHistory] AS [Extent1]
  6. ) AS [GroupBy1]
  7. GO
  8. SELECT TOP (1)
  9. [Extent1].[Id] AS [Id],
  10. [Extent1].[ModelHash] AS [ModelHash]
  11. FROM [dbo].[EdmMetadata] AS [Extent1]
  12. ORDER BY [Extent1].[Id] DESC
  13. GO

这段sql语句其实中只是在开发的时候有用,发布到生产环境,可以把这个给禁用了以提高性能。解决办法:

Application_Start加代码

  1. Database.SetInitializer<lanhuBlog.DAL.BlogContext>(null);

lanhuBlog.DAL.BlogContext这是我项目的EF上下方类,你要根据你的项目替换成自己的EF上下方类。

四、Model和DAl单独的分层的

用vs建一个mvc项目,Model、DAL、Controller、View都在Web项目里面。为了减少model和DAL导致重新编译dll带来的性能影响。我把Model和DAL都单独的分层,编译成单独的dll了。

五、EF Pre-Generated Mapping Views(预生成映射视图)

Application_Start加入下面代码:

  1. using (var dbcontext = new EFDbContext())
  2. {
  3. var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
  4. var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
  5. mappingCollection.GenerateViews(new List<EdmSchemaError>());
  6. //对程序中定义的所有DbContext逐一进行这个操作
  7. }

六、补充

如果你觉得这还没有解决”过了一段时间不访问页面然后再次打开页面变慢“的问题,而且不能忍受第一次访问还是有点慢,可以设置应用程序池的”闲时超时“和回收”固定时间间隔“长一些或者建一个计划任务定时去访问使用了ef的页面,这样给ef热身,让ef不变冷,这样可以防止长时间不请求网站,应用程序进程停止再次访问变慢的问题。设置应用程序池的时间如下图:

闲时超时默认是20分钟,如果在超过20分钟都没有请求这个应用程序池工作进程就要关闭。这里你可以设置根据自己需要设置长一些。

原文地址:https://www.cnblogs.com/quangeshishen/p/8275388.html

时间: 2024-10-16 09:54:53

处理EF第一次加载过慢问题的相关文章

关于EF第一次加载慢或过一段时间不访问时再次访问加载慢问题的总结

优化方案 1.安装Application Initialization 这是在iis8出来后才有的,iis8内置的功能,而对于iis7.5也提供了一个扩展以支持这个功能. Application Initialization Module for IIS 7.5 在页面接近底部的地方,找到适合自己架构的安装链接 x86 for Windows 7 x64 for Windows 7 or Windows Server 2008 R2 安装这个iis模块后,在iis界面中并没有模块图标和配置界面,

页面第一次加载实现图片淡入方式加载

页面第一次加载实现图片淡入方式加载:图片以淡入方式加载总是让人感觉有一种动态的感觉,可以让用户体验更好,下面就简单介绍一下如何实现此效果.当页面加载的时候,让加载好的图片先隐藏,然后再使用fadeIn()函数实现图片的淡入效果,参考代码如下: <script type="text/javascript"> $("#load img").load(function() { $(this).hide(); $(this).fadeIn("5000&

提高网站第一次加载速度

特别是在手机端访问,用户第一次打开网站,如果得到反馈的时间太久,用户很可能在页面完成加载之前就离开,不会再次访问.所以,网站.web App,提高首次访问的加载速度就显得特别重要了.第一次加载速度是用"首字节的时间"测量的,即从用户点击访问到从服务器返回第一个字节所用的时间,绝大多数情况下,真正的原因在于前端,PageSpeed YSlow和其他无数的工具和服务用来解决这些问题. 浏览器是如何加载页面的 解析域名à发起请求à下载响应à渲染页面 当浏览器要渲染页面的时候,如果页面中有CS

C# 将后台数据 写到前台脚本中去【控制页面中某些脚本只在 页面第一次加载的时候才去 执行】

protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { this.domainBind(); Page.RegisterClientScriptBlock("F1", "<script>var c=1</script>"); } else { Page.RegisterClientScriptBlock("F0", &qu

IIS-7.5 第一次加载慢的 解决办法

问题焦点 Win2008R2,Win7 下面IIS部署的.NET站点第一次加载比较慢. 解决办法: 1.基本原理: 在第一个请求到达之前加载Web应用程序,从而提高其网站的响应性.通过主动加载和初始化所有依赖项(如数据库连接.编译ASP.NET代码和加载模块). 2表现为: 通过预加载工作进程减少第一个请求的响应时间 当发生重叠回收时,通过预加载工作进程提高可靠性 3安装配置 3.1.IIS-7.5扩展包 下载地址 https://pan.baidu.com/s/1TfSVOY5WclB9swP

EF中加载实体的方式

加载实体的方式: 1.贪婪加载(eager loading) 2.延迟加载(lazy loading) 3.显示加载(explicit loading) 贪婪加载实现是通过include方法实现的 1 using (var context = new BloggingContext()) 2 { 3 // Load all blogs and related posts 4 var blogs1 = context.Blogs 5 .Include(b => b.Posts) 6 .ToList

EntityFramework(EF)贪婪加载和延迟加载的选择和使用

贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 1 using (var context = new MyDbContext()) 2 { 3 var orders = from o in context.Orders.Include("OrderDetails") select o; 4 } 当读取订单信息orders的时候,我们希望把订单的详细信息也读取出来,那么这里我们使用Include关键字将关联表也加载进 来. 延迟加载:即当我们需要用到的时候才进行加载(读取) 当我们

第一次加载应用时的滑动启动页

首先新建一个类:SplashViewController 还是直接贴代码: .h文件 #import <UIKit/UIKit.h> #import "UIButton+Bootstrap.h" @interface SplashViewController : UIViewController{ } //页数量 @property (nonatomic,assign) NSInteger pagecount; //是否动画 @property (nonatomic, as

EF 首次加载很慢

1.Code First第一次启动会对比程序中的Model与数据库表(database initializer ),生成Model与数据库的映射视图.使用ef6的情况下,在Application_Start里面添加 using (var dbcontext = new NCContext()) { var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext; var mappingCollection = (Stora