2017-05-22 72 views
1

我們的一個開發者的把這個在Global.asax代碼,Application_Start方法:LINQ查詢應放慢全球ASAX

IEnumerable<object> result = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()) 
    where t.GetInterfaces().Contains(typeof(IClassId)) && 
    t.GetConstructor(Type.EmptyTypes) != null 
    select Activator.CreateInstance(t) as IClassId; 

List<IGrouping<Guid, object>> lst = result.GroupBy(x => ((IClassId)x).ClassId) 
    .Where(y => y.Count() > 1) 
    .ToList(); 

當我跑在Visual Studio中的性能分析器,它被認定爲「熱路徑」。

我對此很新,想知道爲什麼會導致經濟放緩。

+0

但是,您沒有給出足夠的信息來有效地回答這個問題,只是因爲某些事物被認定爲「熱門路徑」並不意味着它是。這通常是相對於其他方法或擴展。增加測試用例覆蓋率並評估結果。也就是說,LINQ通常不是最快的,因爲它在處理各種結果的方法中工作。你想找什麼?你可能會專門爲此編寫代碼,並避免LINQ。 –

+2

這段代碼將遍歷整個程序集,它們被應用程序使用並在那裏搜索包含對象的IClassId接口,並查看它是否具有默認構造函數並創建它的實例。如果你有很多組件,這將需要一段時間。 –

回答

2

這看起來像一些自動創建的代碼,用於具有在Web應用程序域中實現IClassId接口的默認構造函數的類。

這是使用反射來獲取所有這些類的實例並將它們存儲在一個數組上。所以,是的,這可能會緩慢或超慢,具體取決於有多少類滿足這些條件。

這不是重度測試,但我認爲它會說明問題。我創建了一個新的空項目,創建了IClassId界面並測量了平均運行時間。我甚至不具有任何類實現的接口,這樣的結果集將爲空:

protected void Application_Start() 
{ 
    //measure the running time 
    var stopWatch = new Stopwatch(); 
    stopWatch.Start(); 

    IEnumerable<object> result = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()) 
     where t.GetInterfaces().Contains(typeof(IClassId)) && 
       t.GetConstructor(Type.EmptyTypes) != null 
     select Activator.CreateInstance(t) as IClassId; 

    List<IGrouping<Guid, object>> lst = result.GroupBy(x => ((IClassId)x).ClassId) 
     .Where(y => y.Count() > 1) 
     .ToList(); 
    stopWatch.Stop(); 

    var elapsed = stopWatch.ElapsedMilliseconds; 

} 

平均用了500毫秒運行這段代碼沒有實現,並沒有其他的組件加載到我的應用程序域比默認VS項目模板程序集。然而,他們中只有少數幾個。在我的情況下約爲28000。你可以做同樣的,看看你有多少:

var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).Count(); 

結論:

我建議你不要使用這種代碼,但設置一個適當的IoC容器代替,因此實例可以根據需要創建並在需要時注入構造函數,而不是在應用程序啓動期間創建它們。