Entity Framework的啓動速度優化

最近開發的服務放到IIS上寄宿以後,遇到一些現象,好比剛部署以後,第一次啓動很慢;程序放置一下子,再次請求也會比較慢。好比第一個問題,能夠解釋爲初次請求某一個服務的時候,須要把程序集加載到內存中可能比較慢,第二個問題有多是IIS的線程回收機制致使放置若干長時間,空閒的進程被回收了,再次請求的話可能比較慢。

剛開始的時候沒有太在乎,可是隨着系統的發佈,這種初次請求,或者閒置若干時間後第一次請求的漫長等待使得App的體驗不好,不少時候App加載好半天數據都沒過來。若是前端沒處理好,還會致使App的假死。因此就花了點功夫研究下什麼緣由致使。html

剛開始的時候,還覺得是WebService的框架出了問題。後面使用App,經過Fiddler看到了,某次請求db.居然長達6s中,而且每次致使請求超時都出如今db.訪問這一塊,這顯然不正常。早期,咱們訪問數據庫使用的是原始的ADO.NET 執行SQL語句,若是有參數的話,參數化防止SQL注入,而後基本的增刪查,經過批量生成存儲過程實現,並在底層框架層記錄了每次服務的訪問語句和次數,這樣便於調優。起初認爲這樣性能是墜吼的,可是隨着規模的擴大,效率過低,因此就切換到了Entity Framework上,經過自動生成實體,而後經過LINQ的方式來實現增刪改查,這樣效率快不少。前端

意識到是數據訪問的問題以後,開始在查找Entity Framework第一次啓動比較慢的問題,而後在網上找了一下,發現不少人都遇到過一樣的問題。解決方案也比較成熟,好比Pre-Generated Mapping Views,NGen等等,下面就逐個來講明,其實這些在網上也有不少,我這裏記錄一下做爲本身之後備查。數據庫

1、Entity Framework初次啓動優化

下面提到的方法,有不少須要Entity Framework版本的支持,因此咱們在使用Entity Framework的時候,最好使用最新版本。緩存

Pre-Generated Mapping Viewsapp

關於使用EntityFramework的注意事項在Performance Considerations for Entity Framework 這篇文章中有詳細介紹,其中生成視圖操做耗時比較多,在Entity Framework執行查詢或者對數據庫進行寫操做的時候,必須生成一些映射視圖來訪問數據庫,這些映射視圖是一系列對數據庫中對象的抽象聲明,這些數據同時也是app domain的緩存元數據的一部分,在同一應用程序做用域裏面,建立多個數據庫訪問上下文時能夠重用這部分對象。由於在第一次查詢的時候,生成映射視圖是比較耗時的,因此關於這一點,具體的詳細操做能夠查看msdn上的Pre-Generated Mapping Views,這篇文章提供了兩種預先生成映射視圖的方法,一種是在Visual Studio中,經過安裝EF Power Tools 插件來生成(如下圖片,來自msdn)。框架

geberateViews(en-us,MSDN_10)

dn469601_generatedViews(en-us,MSDN_10)

這種方式不受EF的版本限制。dom

網站還提供了第二種經過代碼的方式來預先生成視圖,這必需要求EF是6.0及以上版本。這也是博客園這篇文章 來,給Entity Framework熱熱身所使用的方法。通常的,若是是Web站點,能夠放在App_Start中來初始化:ide

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處理來進一步提升速度。post

2、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 加上程序集的路徑和名稱,便可。

好比在個人機器上,能夠看到以下:

NGen

通過這一操做,首次訪問db的速度終於控制到了500ms之內。

以上是EF的優化,解決了首次部署以後,第一次訪問數據庫的問題,對於應用程序放置一下子,再次請求因爲線程池回收致使再次訪問變慢的問題,經過設置IIS解決。

3、IIS設置

將服務或者站點部署到IIS上以後,在對應的線程池裏有兩個地方能夠設置,以下圖:

IIS設置

  • 空閒超時時間,默認是20分鐘,表示在20分鐘之類,若是沒有請求進來,那麼對應的線程就處於閒置狀態,這裏將其改成0。
  • 例常(Regular)回收時間,這裏默認爲1740分鐘,大概是29個小時(爲何是29而不是24,聽說是爲了將回收時間的影響減少到最小化,方便調試找到問題,29是24之後的第一個質數),表示大概每隔29個小時,IIS會回收一次應用程序線程池裏面的線程。

這樣設置以後就能夠解決第二個問題。

4、總結

本文簡單介紹了優化EntityFramework初次啓動速度的方法,以及爲防止IIS線程超時閒置,以及例常線程回收致使的初次運行時間過長的解決方法,但願對您解決上述問題有所幫助。

相關文章
相關標籤/搜索