【问题标题】:How to determine efficiency?如何确定效率?
【发布时间】:2016-01-06 17:15:33
【问题描述】:

如何比较这两个迭代以确定哪个最有效?

Process.GetProcessesByName("EXCEL")
    .Where(p => p.StartTime >= _createdOn)
    .ToList()
    .ForEach(p => p.Kill());

foreach (var proc in Process.GetProcessesByName("EXCEL").Where(p => p.StartTime >= _createdOn))
    proc.Kill();

【问题讨论】:

  • 使用诊断名称空间中的秒表计时(假设您的意思是手动)。但是,您确实在 VS 中有某些工具可以让您分析您的代码。
  • 但要注意过早的优化。除非您发现严重的性能问题,否则这可能不是问题。
  • Semi-relevant blog post - 或许不是第一点,但其余的关于它是否值得担心。
  • 非常好的点。我想知道它是否对时间很重要。对于这种情况(因为两者都很快),我不确定效率是否可以通过时间来衡量。我想知道每个如何编译为 CLR。​​
  • 我同上上述 cmets,基于我对您的代码上下文所做的假设 - 我会说性能差异可以忽略不计。但请注意 - 在某些情况下,是否调用 ToList 之间的区别可能绝对很重要。 ToList 将去获取整个集合(例如,从数据库中),而在需要时迭代一个实现良好的 IEnumerable 可能MoveNext。这称为延迟加载,它可能很重要。

标签: c# lambda clr


【解决方案1】:

实际差异只能通过在精确情况下双向运行并使用Stopwatch 或其他分析工具测量来确定,但是这里有一些观察结果:

  • 唯一真正的区别是调用ToList() 是使用.ForEach() 所必需的。除此之外,它们是等价的。
  • 因为我假设这不会经常运行(您需要多久杀死每个 Excel 进程?)在这种情况下性能差异应该是无关紧要的。
  • 您可能正在修复症状而不是问题。我很好奇为什么你有多个需要杀死的 excel 进程。

【讨论】:

  • 您还没有回答问题。它需要详细说明“如何”,即您提到的“测量”。
  • @JᴀʏMᴇᴇ “我如何比较这两个迭代以确定哪个最有效?” --> “实际差异只能通过在精确情况下双向运行并测量来确定,”
  • 所以你的答案是双向运行和测量?这是 C# 特有的问题,至少需要基于 C# 的答案。这太模糊了。
  • Excel 进程与问题的关系是任意的。问题实际上是“foreach”与“ToList().ForEach”。我不是在解决症状,我只是在要求效率。我只是重构产生问题的遗留代码。
  • @DanAndrews 对于问题一般来说可能是任意的,但它可能会通过关注问题而不是来帮助OP症状。经典的XY Problem
【解决方案2】:

它们几乎完全相同。这里耗时的操作是Process.GetProcessesByName("EXCEL")p.StartTimeproc.Kill()。在这两种情况下,您都在做同样数量的事情。其他一切都只需要很短的时间。如果你想在这里进行一些真正的优化,你可以尝试用 WinAPI 来做那些长时间的操作,有时它会更快。

编辑: 我之前为我自己的项目测量了这些操作的速度。但是我没有确切的数字,所以我重新检查了一遍。

这些是我的结果:

Process.GetProcessesByName():

DateTime start = DateTime.Now;
for (int i = 0 ; i < 1000 ; i++) {
    Process.GetProcessesByName("chrome");
}
TimeSpan duration = DateTime.Now - start;

每 1000 次操作需要 5 秒

p.Kill():

TimeSpan duratiom = TimeSpan.Zero;
for (int i = 0 ; i < 1000 ; i++) {
    Process p = Process.Start("c:/windows/notepad");
    DateTime start = DateTime.Now;
    p.Kill();
    duratiom += DateTime.Now - start;
}

每 1000 次操作需要 300 毫秒。仍然是一个很大的数字。

还有 StartTime,只是比较数字:

没有 p.StartTime:

Process[] ps = Process.GetProcessesByName("chrome");
DateTime start = DateTime.Now;
for (int i = 0 ; i < 1000 ; i++) {
    ps.Where(p => true).ToList();
}
TimeSpan duratiom = DateTime.Now - start;

6 毫秒

使用 p.StartTime:

Process[] ps = Process.GetProcessesByName("chrome");
DateTime start = DateTime.Now;
for (int i = 0 ; i < 1000 ; i++) {
    ps.Where(p => p.StartTime < DateTime.Now).ToList();
}
TimeSpan duratiom = DateTime.Now - start;

408 毫秒

所以,这些数字告诉我没有必要优化 .Where()、ToList() 或 foreach。无论如何,使用 Process 的操作需要花费数十倍的时间。另外,我了解分析器,并使用它们来测量和优化,但我制作这些示例是为了获得准确的数字并说明要点。

【讨论】:

  • 为什么延迟执行会有问题? (注意Process.GetProcessesByName 返回一个Process[]。)
  • 糟糕的答案。 Time consuming operations here are 你怎么知道什么是耗时的,什么不是?阅读我上面关于ToList的评论。
  • @JᴀʏMᴇᴇ 我编辑了我的答案,添加了一些例子来更好地解释我的观点。还可怕吗?
  • @RyanO'Hara 我猜你是对的,我删除了那部分。
猜你喜欢
  • 2022-01-25
  • 2011-06-22
  • 2019-12-03
  • 1970-01-01
  • 2015-10-08
  • 2022-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多