2015-09-24 47 views
2

我正在评估C#.NET Web应用程序中的性能问题,并将瓶颈追踪到链式lambda表达式。我想完全删除lambda表达式,所以我可以评估链中每个步骤的性能,但我对lambda表达式相对较新。有没有人对如何将第二个lambda表达式重构为更传统的代码有任何想法,以便每个步骤或动作都可以跟踪?消除.net lambda表达式

IEnumerable<OurPerformance> validPerformances = package.TimeFilteredValidPerformances(visitDateAndTime); 

IEnumerable<WebPerformance> webPerformances = performanceGroup.RegularNonPassedPerformances 
      .Where(performance => validPerformances.Select(perf => perf.PerformanceId).Contains(performance.PerformanceId))     
      .Select(performance => 
       new WebPerformance 
       { 
        Date = performance.PerformanceDate.ToJavaScriptDateString(), 
        PerformanceId = performance.PerformanceId, 
        Title = performance.UserFriendlyTitle, 
        ProductionSeasonId = performance.ProductionSeasonId, 
        AvailableCount = performance.AvailableCount 
       }); 

**IEnumerable<WebProduction> webProductions = webPerformances 
      .GroupBy(performance => performance.ProductionSeasonId) 
      .ToDictionary(grouping => SheddProduction.GetOurProduction(grouping.Key), grouping => grouping.ToList()) 
      .Select(perfsByProduction => 
       new WebProduction 
       { 
        ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber, 
        Duration = perfsByProduction.Key.Duration, 
        Title = perfsByProduction.Key.UserFriendlyTitle, 
        Synopsis = perfsByProduction.Key.UserFriendlySynopsis, 
        ThumbnailImage = perfsByProduction.Key.PreviewImage, 
        Performances = perfsByProduction.Value 
       });** 
+0

为什么你要同时使用ToDictionary和GroupBy? “ToDictionary”似乎不必要。 – dbc

回答

1

它实际上很简单,可以将其分解为更小的片段,这些片段更明显地转换为“传统”代码。只是每个LINQ表达式的结果存储在这样的局部变量:

var groupedWebPerformances = webPerformances.GroupBy(performance => performance.ProductionSeasonId); 
var webPerformancesDictionary = groupedWebPerformances .ToDictionary(grouping => SheddProduction.GetOurProduction(grouping.Key), grouping => grouping.ToList()); 
IEnumerable<WebProduction> webProductions = webPerformancesDictionary.Select(perfsByProduction => 
       new WebProduction 
       { 
        ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber, 
        Duration = perfsByProduction.Key.Duration, 
        Title = perfsByProduction.Key.UserFriendlyTitle, 
        Synopsis = perfsByProduction.Key.UserFriendlySynopsis, 
        ThumbnailImage = perfsByProduction.Key.PreviewImage, 
        Performances = perfsByProduction.Value 
       }); 

话虽这么说,你的表现的问题是,你使用IEnumerable无处不在。 IEnumerable可能会在每次使用它们时重新评估(取决于底层类型是什么),所以validPerformances正在针对RegularNonPassedPerformances中的每个项目重新评估一次,并且webPerformances中的每个项目都未被评估,直到整个枚举被强制为评估,因此性能问题似乎是后来却是最有可能在这里:

validPerformances.Select(perf => perf.PerformanceId).Contains(performance.PerformanceId) 

确保你强迫所有可枚举通过对他们做了ToList来评估一个单一的时间,他们都是这样创建时:

List<OurPerformance> validPerformances = package.TimeFilteredValidPerformances(visitDateAndTime).ToList(); 

List<WebPerformance> webPerformances = performanceGroup.RegularNonPassedPerformances 
      .Where(performance => validPerformances.Select(perf => perf.PerformanceId).Contains(performance.PerformanceId))     
      .Select(performance => 
       new WebPerformance 
       { 
        Date = performance.PerformanceDate.ToJavaScriptDateString(), 
        PerformanceId = performance.PerformanceId, 
        Title = performance.UserFriendlyTitle, 
        ProductionSeasonId = performance.ProductionSeasonId, 
        AvailableCount = performance.AvailableCount 
       }) 
      .ToList(); 

List<WebProduction> webProductions = webPerformances 
      .GroupBy(performance => performance.ProductionSeasonId) 
      .ToDictionary(grouping => SheddProduction.GetOurProduction(grouping.Key), grouping => grouping.ToList()) 
      .Select(perfsByProduction => 
       new WebProduction 
       { 
        ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber, 
        Duration = perfsByProduction.Key.Duration, 
        Title = perfsByProduction.Key.UserFriendlyTitle, 
        Synopsis = perfsByProduction.Key.UserFriendlySynopsis, 
        ThumbnailImage = perfsByProduction.Key.PreviewImage, 
        Performances = perfsByProduction.Value 
       }) 
      .ToList(); 
+0

关于linq和lazy-evaluation的一个很好的入门书籍:http://blogs.msdn.com/b/ericwhite/archive/2006/10/04/lazy-evaluation-_2800_and-in-contrast_2c00_-eager-evaluation_2900_.aspx – mydogisbox

+0

I有这个确切的例子,但你击败了我。 – DVK

+0

@DVK比DVK的速度快! – mydogisbox

2

我不能建议任何算法来排除lambda表达式,但我有另一个建议。尝试使用List for webPerformances而不是IEnumerable集合。 调用ToList()获取List web性能。在这种情况下,第二个lambda表达式将与列表一起工作,并且不会重新评估IEnumerable集合。

1

这里是羊肉你的第二个lambda表达式的-重构为“传统”代码:

IEnumerable<IGrouping<string, WebProduction>> groupedPerformances 
    = webPerformances.GroupBy(performance => performance.ProductionSeasonId); 

var dictionary = new Dictionary<string, List<WebProduction>>(); 
foreach (IGrouping<string, WebProduction> grouping in groupedPerformances) 
{ 
    var group = new List<WebProduction>(); 
    foreach (WebProduction webProduction in grouping) 
     group.Add(webProduction); 

    dictionary.Add(grouping.Key, group); 
} 

var result = new List<WebProduction>(); 
foreach (KeyValuePair<string, List<WebProduction>> item in dictionary) 
{ 
    var wp = new WebProduction 
    { 
     ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber, 
     Duration = perfsByProduction.Key.Duration, 
     Title = perfsByProduction.Key.UserFriendlyTitle, 
     Synopsis = perfsByProduction.Key.UserFriendlySynopsis, 
     ThumbnailImage = perfsByProduction.Key.PreviewImage, 
     Performances = perfsByProduction.Value 
    }; 
    result.Add(wp); 
} 

我不知道结果类型的SheddProduction.GetOurProduction方法,因此我做了细微的变化,但你可以得到的要点...