EF優化之啟動預熱


為什么Entity Framework的初始化速度慢如蝸牛呢?

對於在應用程序中定義的每個DbContext類型,在首次使用時,Entity Framework都會根據數據庫中的信息在內存生成一個映射視圖(mapping views),而這個操作非常耗時。

在第1次調用DbContext進行數據庫操作時會進行緩慢的mapping views生成操作,后續的DbContext操作會共享已經生成的mapping views,不受這個問題影響。但是要注意的是你定義的每一個DbContext都會面臨這個問題。

而我們的緩解之道則是在應用程序初始化時一次性觸發所有的DbContext進行mapping views的生成操作——調用StorageMappingItemCollection的GenerateViews()方法。

 一、預生成映射視圖

將代碼放在Application_Start中調用PreApplicationStartMethod中執行

 private void PreApplicationStartMethod()
        {
            using (var dbcontext = new XXXDBContext())
            {
                var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
                var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace); mappingCollection.GenerateViews(new List<EdmSchemaError>());
            }  //對程序中定義的所有DbContext逐一進行這個操作
        }

在程序更新時只需發一個請求讓程序啟動起來,比如訪問首頁,就可以直接發布。而第1位用戶,等待時間由原來7秒減少到0.5-0.6秒。

 二、禁用第一次ef查詢對表__MigrationHistory的問題

使用了ef的Code first會在第一次ef查詢的時候會對__MigrationHistory訪問,是為了檢查數據庫和model是否匹配,以保證ef能正常運行。

通過監測會先執行下面的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語句其實中只是在開發的時候有用,發布到生產環境,可以把這個給禁用了以提高性能。

解決辦法:Application_Start加代碼

 protected void Application_Start()
        { 
             //.......
            RouteConfig.RegisterRoutes(RouteTable.Routes);
             
#if DEBUG
            BundleTable.EnableOptimizations = false;//關閉文件壓縮功能
#else
            BundleTable.EnableOptimizations = true;//開啟文件壓縮功能
            Database.SetInitializer<MMISDBContext>(null);
#endif
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            PreApplicationStartMethod();
        }

MMISDBContext這是我項目的EF上下方類,你要根據你的項目替換成自己的EF上下方類。

三、安裝Application Initialization

這是在iis8出來后才有的,iis8內置的功能,一些是iis10的配置圖

 

而對於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的本地鏡像。

 4.查看是否在本機映像緩存中,也列出了依賴子的相關類庫
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen display EntityFramework

文檔:https://docs.microsoft.com/zh-cn/dotnet/framework/tools/ngen-exe-native-image-generator

五、IIS閑置超時導致變冷

如果你覺得這還沒有解決”過了一段時間不訪問頁面然后再次打開頁面變慢“的問題,而且不能忍受第一次訪問還是有點慢,可以設置應用程序池的”閑時超時“和回收”固定時間間隔“長一些或者建一個計划任務定時去訪問使用了ef的頁面,這樣給ef熱身,讓ef不變冷,這樣可以防止長時間不請求網站,應用程序進程停止再次訪問變慢的問題。設置應用程序池的時間如下圖:

閑時超時默認是20分鍾,如果在超過20分鍾都沒有請求這個應用程序池工作進程就要關閉。這里你可以設置根據自己需要設置長一些。

六、Model和DAl單獨的分層的

用vs建一個mvc項目,Model、DAL、Controller、View都在Web項目里面。為了減少model和DAL導致重新編譯dll帶來的性能影響。我把Model和DAL都單獨的分層,編譯成單獨的dll了。
這一點,我比較不理解,路過的高手請指點下
 

 

原文:

https://blog.csdn.net/qq61714079/article/details/50540318

https://msdn.microsoft.com/en-us/data/dn469601#code

https://msdn.microsoft.com/zh-cn/library/dn292691(v=vs.113).aspx

https://www.cnblogs.com/sunShineJing/p/5083184.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM