[英]C#, lambda : How are redundant calls handled?
我很好奇编译器如何处理以下表达式:
var collapsed = elements.GroupBy(elm => elm.OrderIdentifier).Select(group => new ModelsBase.Laser.Element()
{
CuttingDurationInSeconds = group.Sum(itm => itm.CuttingDurationInSeconds),
FladderDurationInSeconds = group.Sum(itm => itm.FladderDurationInSeconds),
DeliveryDate = group.Min(itm => itm.DeliveryDate),
EfterFladderOpstilTid = group.First().EfterFladderOpstilTid,
EfterRadanOpstilTid = group.First().EfterRadanOpstilTid,
});
如您所见,我使用了两次组总和,所以有人知道“组”列表是否会被迭代两次以获得两个总和,还是会对其进行优化,因此实际上只有 1 次完整的列表迭代。
LINQ 通常不是实现高性能的最佳方式,您获得的是编程的生产力,无需太多代码即可获得结果。
优化的可能性是有限的。 在查询到 SQL 的情况下,有一个经验法则:一个查询优于两个查询。
1)到SQL_Server只有一次往返
2) SQL Server 是用来优化这些查询的,如果服务器知道你下一步要做什么,优化就会越来越好。 优化是针对每个查询进行的,而不是针对多个查询进行的。
在 Linq to Objects 的情况下,构建大量查询绝对没有任何好处。 正如您的示例所示,它可能会导致多次迭代。 你让你的代码更简单、更容易阅读——但你放弃了控制,因此放弃了性能。
编译器当然不会优化其中的任何一个。
如果这是使用 LINQ to Objects,因此是委托,则委托将针对 5 个属性对每个组迭代 5 次。
如果这是使用 LINQ to SQL、实体框架或类似的东西,因此使用表达式树,那么基本上由查询提供程序来适当地优化它。
您可以通过在分组键中添加两个字段来优化您的请求
var collapsed = elements.GroupBy(elm => new{
OrderIdentifier=elm.OrderIdentifier,
EfterFladderOpstilTid=elm.EfterFladderOpstilTid,
EfterRadanOpstilTid=elm.EfterRadanOpstilTid
})
.Select(group => new ModelsBase.Laser.Element()
{
CuttingDurationInSeconds = group.Sum(itm => itm.CuttingDurationInSeconds),
FladderDurationInSeconds = group.Sum(itm => itm.FladderDurationInSeconds),
DeliveryDate = group.Min(itm => itm.DeliveryDate),
EfterFladderOpstilTid = group.Key.EfterFladderOpstilTid,
EfterRadanOpstilTid = group.Key.EfterRadanOpstilTid,
});
或者通过使用 LET 语句
var collapsed = from groupedElement in
(from element in elements
group element by element.OrderIdentifier into g
select g)
let First = groupedElement.First()
select new ModelsBase.Laser.Element()
{
CuttingDurationInSeconds = groupedElement.Sum(itm => itm.CuttingDurationInSeconds),
FladderDurationInSeconds = groupedElement.Sum(itm => itm.FladderDurationInSeconds),
DeliveryDate = groupedElement.Min(itm => itm.DeliveryDate),
EfterFladderOpstilTid = First.EfterFladderOpstilTid,
EfterRadanOpstilTid = First.EfterRadanOpstilTid
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.