消除.net lambda表达式
本文关键字:表达式 lambda net 消除 | 更新日期: 2023-09-27 18:14:23
我正在评估我的c# . net web应用程序中的性能问题,并跟踪瓶颈到链式lambda表达式。我想完全删除lambda表达式,这样我就可以评估链中每个步骤的性能,但是我对lambda表达式相对较新。有没有人对如何将第二个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
});**
我不能建议任何算法来排除lambda表达式,但我有另一个建议。尝试使用列表的webperformance代替IEnumerable集合。调用ToList()获取webperformance列表。在这种情况下,第二个lambda表达式将与list一起工作,而不会重新计算IEnumerable集合。
将其分解为更小的部分,更明显地转换为"传统"代码,实际上是相当直接的。只需将每个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();
下面是将第二个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
方法的结果类型,因此我做了一些小的改变,但你可以得到要点…