MVC5中EF6 Code First启动慢及间隙变慢的一些优化处理
第一、問題原因分析
EF方面的原因: 1、Code First第一次啟動會對比程序中的Model與數(shù)據(jù)庫表(database initializer ),生成Model與數(shù)據(jù)庫的映射視圖 2、隨著EF的開源,EF從6開始就不會包含在.net Framework中,安裝.net Framework默認(rèn)是不會安裝EF的。因此EF程序集就沒有生成本地鏡像,這樣每次程序啟動,EF的代碼都會通過just-in-time (JIT) compiler(即時(shí)編譯器)把MSIL中間代碼編譯成本機(jī)能識別的本地代碼。因?yàn)檫@個(gè)生成的本地代碼存在程序運(yùn)行的進(jìn)程里面的內(nèi)存中,它將回收當(dāng)程序進(jìn)程被終止(例如:iis程序池回收,程序池默認(rèn)是按需觸發(fā)運(yùn)行的,沒人訪問它就不啟動了)。由于EF框架還是比較大的,EF6文件大小到4-5M了,所以每次啟動都要重寫編譯本地代碼有比較明顯的性能影響。 拋開EF框架程序啟動慢的問題主要有以下兩方面的原因: 1、站點(diǎn)更新后重新加載程序文件; 2、iis程序池回收后也會需要重新加載(程序池默認(rèn)是按需觸發(fā)運(yùn)行的,沒人訪問它就不啟動了)MVC的程序第一次訪問比較慢的的問題由于第一次是要處理視圖文件.cshtml(生成為.cs文件)、加載引用的dll程序文件和初始化程序池等等。
第二、優(yōu)化方案
我主要是通過以下幾方面來優(yōu)化一、安裝Application Initialization
這是在iis8出來后才有的,iis8內(nèi)置的功能,而對于iis7.5也提供了一個(gè)擴(kuò)展以支持這個(gè)功能。
Application Initialization Module for IIS 7.5
在頁面接近底部的地方,找到適合自己架構(gòu)的安裝鏈接
- x86 for Windows 7
- x64 for Windows 7 or Windows Server 2008 R2
安裝這個(gè)iis模塊后,在iis界面中并沒有模塊圖標(biāo)和配置界面,還需要安裝:
https://yunpan.cn/OcMvrRKi3a8Wbu ?訪問密碼 ce02
安裝成功之后會多了一個(gè)配置如下圖:
如果僅配置程序池StartMode為AlwaysRunning還不放心的話,
也可以同時(shí)針對站點(diǎn)開啟preload和DoAppInitAfterRestart。
設(shè)置應(yīng)用程序池如下圖:
設(shè)置網(wǎng)站如下圖
配置好后,測試了下,效果十分不錯(cuò)。
回收程序池后首次打開各站點(diǎn),延遲都很低。
其實(shí)這個(gè)模塊的思路和定時(shí)從外部觸發(fā)一個(gè)訪問是一樣的,只是,更好的地方在于,它本身在程序池回收重啟的時(shí)候就完成了這件事,而不會讓外部訪問有機(jī)會遇到首次訪問的情況。
二、用Ngen安裝生成EF的本地鏡像
1、打開cmd窗口 2、定位到dll所在的目錄,如:cd d:\website1\bin,切換到程序的bin目錄。 3、運(yùn)行ngen命令 For 32 bit run: %WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install EntityFramework.SqlServer.dllFor 64 bit run:
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install EntityFramework.SqlServer.dll 注意:這里根據(jù)你自己機(jī)器(是32還是64)和.net版本,選擇相應(yīng)的命令,只需要安裝EntityFramework.SqlServer.dll,因?yàn)榘惨蕾嘐ntityFramework.dll,會自動安裝生成EntityFramework.dll的本地鏡像。三、禁用第一次ef查詢對表__MigrationHistory的問題
使用了ef的Code first會在第一次ef查詢的時(shí)候會對__MigrationHistory訪問,是為了檢查數(shù)據(jù)庫和model是否匹配,以保證ef能正常運(yùn)行。通過監(jiān)測會先執(zhí)行下面的sql:
?
SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT COUNT(1) AS [A1] FROM [dbo].[__MigrationHistory] AS [Extent1] ) AS [GroupBy1] GO SELECT TOP (1) [Extent1].[Id] AS [Id], [Extent1].[ModelHash] AS [ModelHash] FROM [dbo].[EdmMetadata] AS [Extent1] ORDER BY [Extent1].[Id] DESC GO?
這段sql語句其實(shí)中只是在開發(fā)的時(shí)候有用,發(fā)布到生產(chǎn)環(huán)境,可以把這個(gè)給禁用了以提高性能。解決辦法:
Application_Start加代碼 Database.SetInitializer<Magicodes.WeiChat.Data.AppDbContext>(null); Magicodes.WeiChat.Data.AppDbContext這是我項(xiàng)目的EF上下方類,你要根據(jù)你的項(xiàng)目替換成自己的EF上下方類。?四、Model和DAl單獨(dú)的分層的
為了減少model和DAL導(dǎo)致重新編譯dll帶來的性能影響。把Model和DAL都單獨(dú)的分層,編譯成單獨(dú)的dll。?五、EF Pre-Generated Mapping Views(預(yù)生成映射視圖)
Application_Start加入下面代碼: using (var dbcontext = newAppDbContext()){
var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
mappingCollection.GenerateViews(new List<EdmSchemaError>()); //對程序中定義的所有DbContext逐一進(jìn)行這個(gè)操作
}
?
六、補(bǔ)充
如果你覺得這還沒有解決”過了一段時(shí)間不訪問頁面然后再次打開頁面變慢“的問題,而且不能忍受第一次訪問還是有點(diǎn)慢,可以設(shè)置應(yīng)用程序池的”閑時(shí)超時(shí)“和回收”固定時(shí)間間隔“長一些或者建一個(gè)計(jì)劃任務(wù)定時(shí)去訪問使用了EF的頁面,這樣給ef熱身,讓EF不變冷,這樣可以防止長時(shí)間不請求網(wǎng)站,應(yīng)用程序進(jìn)程停止再次訪問變慢的問題。設(shè)置應(yīng)用程序池的時(shí)間如下圖:
閑時(shí)超時(shí)默認(rèn)是20分鐘,如果在超過20分鐘都沒有請求這個(gè)應(yīng)用程序池工作進(jìn)程就要關(guān)閉。這里你可以設(shè)置根據(jù)自己需要設(shè)置長一些。
備注:以上內(nèi)容參考了http://www.lanhusoft.com
轉(zhuǎn)載于:https://www.cnblogs.com/smileyearn/p/5819676.html
總結(jié)
以上是生活随笔為你收集整理的MVC5中EF6 Code First启动慢及间隙变慢的一些优化处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tomcat中组件的生命周期管理(三)
- 下一篇: .net MVC4.0项目发布到阿里云虚