Ana*_*oly -1 c# linq performance
private void GenerateRecords(JobRequest request)
{
for (var day = 0; day < daysInRange; day++)
{
foreach (var coreId in request.CoreIds)
{
foreach (var agentId in Enumerable.Range(0, request.AgentsCount).Select(x => Guid.NewGuid()))
{
for (var copiesDone = 0; copiesDone < request.CopiesToMake; copiesDone++)
{
foreach (var jobInfoRecord in request.Jobs)
{
foreach (var status in request.Statuses)
{
//DoSomeWork();
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法提高多次迭代的性能?我真的需要所有这些循环,但我想知道如何改进(加速)迭代?也许使用linq?
一旦你放弃了 LINQ,你就会受到收集枚举器和垃圾收集器的摆布。
如果您想从foreach循环中获得尽可能多的性能并且可以控制数据结构,请确保使用具有结构枚举器(即List<T>, ImmutableArray<T>)的集合类型。更好的是,在可行的情况下使用普通的通用数组。尽管有一个非结构体枚举器,但就原始访问速度而言,它们是 .NET 中最快的集合类型,至少在 Release 中构建/启用优化时(在这种情况下,编译器为foreach数组上的循环发出相同的 IL它将 forfor循环,从而减少通常与使用实现的类型相关联的分配和方法调用IEnumerable<T>。
Roslyn 有一组热代码路径指南,这些指南在您的情况下很有用:
- 避免使用 LINQ。
- 避免在没有结构枚举器的集合上使用 foreach。
现在,以上内容在任何性能关键的场景中都是有效的。但是,我有点怀疑集合迭代性能是您特定情况下的瓶颈。这是更有可能的是DoSomeWork花费的时间比你想。您应该分析您的GenerateRecords方法调用以获得关于哪些代码位最需要关注的明确答案。
如果您认为您的DoSomeWork实施是最佳的,请考虑并行化您的工作负载。
如果您的DoSomeWork实现是纯粹的并且不依赖于外部可变状态(即类变量),您就可以通过Parallel.For或并行化您的某些循环迭代Parallel.ForEach。您的最外层循环看起来是一个特别好的候选者,但您可能必须尝试放置并行循环,直到获得所需的性能特征。作为起点,我建议:
private void GenerateRecords(JobRequest request)
{
Parallel.For(0, daysInRange, day =>
{
foreach (var coreId in request.CoreIds)
{
for (var i = 0; i < request.AgentsCount; i++)
{
var agentId = Guid.NewGuid();
for (var copiesDone = 0; copiesDone < request.CopiesToMake; copiesDone++)
{
foreach (var jobInfoRecord in request.Jobs)
{
foreach (var status in request.Statuses)
{
//DoSomeWork();
}
}
}
}
}
});
}
Run Code Online (Sandbox Code Playgroud)