gpt4 book ai didi

c# - FirstOrDefault() 的性能

转载 作者:太空狗 更新时间:2023-10-29 21:50:46 29 4
gpt4 key购买 nike

<分区>

查看我今天使用性能分析器处理的 Web 应用程序的一部分。我以为 Union 导致了一些延迟,但发现了其他令人惊讶的结果。

减速的原因之一似乎是 FirstOrDefault。

这是一个非常简单的 LINQ 查询,如下所示:

foreach(Report r in reports)
IDTOStudy study = studies.FirstOrDefault(s => s.StudyID == r.StudyID);

我创建了一个小方法来复制我认为 FirstOrDefault 正在执行的行为。

private IDTOStudy GetMatchingStudy(Report report, IList<IDTOStudy> studies)
{
foreach (var study in studies)
if (study.StudyID == report.StudyID)
return study;

return null;
}

此方法将 FirstOrDefault 替换为如下所示:

foreach(Report r in reports)
IDTOStudy study = GetMatchingStudy(r, studies);

查看与性能分析器一起运行的新代码表明 FirstOrDefault 的完成时间是我的新方法的两倍。看到这一幕令人震惊。

我一定是对 FirstOrDefault() 查询做错了什么。它是什么?

FirstOrDefault() 是否完成了整个查询,然后取第一个元素?

我怎样才能加快速度并使用 FirstOrDefault()

编辑 1:

我注意到的另外一点是,探查器说我在这两种实现上都在用尽我的 CPU。这也是我不关心和没想到的事情。我添加的额外方法并没有减少尖峰,只是将其持续时间减半。

编辑 3:

将研究放入字典中极大地缩短了运行时间。这肯定会是提交代码的样子。不过不回答有关 FirstOrDefault 的问题。

编辑 2:

这是在一个简单的控制台应用程序中请求的示例代码。我的运行仍然表明,在大多数情况下,FirstOrDefault 需要更长的时间。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Diagnostics;

namespace TestCode
{
public class Program
{
public List<IntHolder> list;

public static void Main(string[] args)
{
var prog = new Program();
prog.list = new List<IntHolder>();

prog.Add50000Items();
prog.list.Add(new IntHolder() { Num = 12345 });
prog.Add50000Items();

var stopwatch = new Stopwatch();
stopwatch.Start();
prog.list.FirstOrDefault(n => n.Num == 12345);
stopwatch.Stop();

Console.WriteLine("First run took: " + stopwatch.ElapsedTicks);
var lookingFor = new IntHolder() { Num = 12345 };

stopwatch.Reset();
stopwatch.Start();
prog.GetMatching(lookingFor);
stopwatch.Stop();
Console.WriteLine("Second run took: " + stopwatch.ElapsedTicks);
Console.ReadLine();
}

public void Add50000Items()
{
var rand = new Random();

for (int i = 0; i < 50000; i++)
list.Add(new IntHolder() { Num = rand.Next(100000) });
}

public IntHolder GetMatching(IntHolder num)
{
foreach (var number in list)
if (number.Num == num.Num)
return number;

return null;
}
}

public class IntHolder
{
public int Num { get; set; }
}
}

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com