2012-09-24 22 views
10

我試圖減少基於EF的應用程序的啓動時間,但是我發現無法減少初始讀取時間低於7秒的時間,即使對於單一實體上下文。特別奇怪的是,這次不是特定於上下文類型的。即使對於微小的DbContext也需要7秒的EF啓動時間

任何人都可以解釋導致這些緩慢時間和/或如何讓事情運行得更快嗎?

下面是完整的示例代碼:

在我的數據庫,我有一個名爲se_stores與主鍵列AptId表:

// a sample entity class 
public class Apartment 
{ 
    public int AptId { get; set; } 
} 

    // two identical DbContexts   

public class MyDbContext1 : DbContext 
{ 
    public MyDbContext1(string connectionString) : base(connectionString) 
    {   
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     Database.SetInitializer<MyDbContext1>(null); 

     var config = new EntityTypeConfiguration<Apartment>(); 
     config.HasKey(a => a.AptId).ToTable("se_stores"); 
     modelBuilder.Configurations.Add(config); 

     base.OnModelCreating(modelBuilder); 
    } 
} 

public class MyDbContext2 : DbContext 
{ 
    public MyDbContext2(string connectionString) 
     : base(connectionString) 
    { 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     Database.SetInitializer<MyDbContext2>(null); 

     var config = new EntityTypeConfiguration<Apartment>(); 
     config.HasKey(a => a.AptId).ToTable("apartments"); 
     modelBuilder.Configurations.Add(config); 

     base.OnModelCreating(modelBuilder); 
    } 
} 

    // finally, I run this code using NUnit: 

var start = DateTime.Now; 
var apt1 = new MyDbContext1(connectionString).Set<Apartment>().FirstOrDefault(); 
var t1 = DateTime.Now - start; 
start = DateTime.Now; 
var apt2 = new MyDbContext2(connectionString).Set<Apartment>().FirstOrDefault(); 
var t2 = DateTime.Now - start; 
Console.WriteLine(t1.TotalSeconds + ", " + t2.TotalSeconds); 

它可靠地打印類似如下:7.5277527,0.060006。當我首先使用MyDbContext2切換測試時,我得到了相同的結果(所以它發生在任何一個DbContext被首先初始化的情況下)。我還嘗試使用EF電動工具預先生成視圖。這將第一個環境的時間縮短到了大約6.8秒,因此只是一個小小的勝利。

據我所知,DateTime.Now是一種可怕的性能分析方法,但是這些結果在使用dotTrace時仍然存在。我也知道,第一次運行一些代碼會調用JITing成本,但是7秒似乎太高而無法歸因於此。

我使用EF 4.3.1和.NET 4 VS 2010

預先感謝您的幫助!

編輯:有人建議打開SQL連接可能會導致問題。

  1. 我第一次嘗試運行一個隨機查詢使用原始SqlConnection和創建命令具有相同的連接字符串。這花了1秒鐘,並沒有影響DbContext初始化的時間。
  2. 然後我試着用連接字符串創建一個SqlConnection並將它傳遞給需要連接的DbContext構造函數。我傳遞了contextOwnsConnection = false。這在DbContext初始化時間中也沒有區別。
  3. 最後,我嘗試使用相同的證書和連接字符串選項通過管理工作室進行連接。這幾乎是瞬間的。
  4. 在dotTrace配置文件中,它測量SqlConnectionFactory.CreateConnection(connectionString)爲0.7秒,這與原始SQL時間一致。

編輯:我想知道延遲是每個連接或只有一次。因此,我試圖讓MyDbContext1和MyDbContext2連接到不同服務器上完全不同的數據庫。無論首先連接哪個數據庫,這個DID都沒有什麼不同:使用第一個DbContext花費了大約7秒,而使用第二個上下文非常快。

+0

[性能注意事項(實體框架)](http://msdn.microsoft.com/en-us/library/cc853327.aspx) – jrummell

+0

@jrummell:這是一個很好的鏈接(我已經閱讀過)。您認爲是否有特定的部分解決了我的問題? – ChaseMedallion

+0

首先,你應該使用StopWatch類來做時機。它更準確。其次,預生成視圖可能會有所幫助(但在這樣一個小環境下,我看不出它會有多大幫助)。您可以使用EF Power Tools從DbContext自動生成視圖。 –

回答

7

在將代碼寫入自己的項目後,我發現項目的平臺目標對EF框架的啓動時間有很大的影響。

針對x64平臺時,我收到了類似於您的結果(第一個DbContext上旋轉了7秒,第二個旋轉了1秒鐘)。當針對x86時,第一個DbContext的啓動時間減少了大約4秒,降低到了3.34633秒,而第二個DbContext花費了與x64情況類似的時間。

我不知道爲什麼會發生這種情況,但它必須與實體框架在不同環境中初始化自身的方式有關。我已經發布了一個關於here的單獨問題。

1

根據幾條評論,第二條運行如此之快的原因是由於連接管理器緩存了連接。這導致我相信獲得最初的連接是問題。

事情嘗試:

  1. 更改連接字符串使用數據庫服務器的IP地址,而不是它的名字。

  2. 使用SQL Management Studio使用完全相同的憑證和機制連接到數據庫服務器。從需要7秒鐘的機器上完成。假設需要一段時間,請調查以查看正在使用哪些協議,並確保所需的協議是列表中的第一個協議。

  3. 將網絡分析儀放在您的機器上,並觀察它的功能。

+0

我的連接字符串已經在使用靜態IP地址(#1)。我也試過#2,發現連接是瞬間完成的。因此,我決定放棄設置#3。我還注意到,這個問題似乎是一個大型解決方案所獨有的。任何其他想法? – ChaseMedallion

相關問題