为什么如果我运行一次方法,如果我在循环 c# 中运行几次,几乎同时完成工作

本文关键字:如果 运行 几次 工作 一次 方法 为什么 循环 | 更新日期: 2023-09-27 18:34:37

我做了一个方法,他做了一些简单的操作,如+,-,*,/。我需要运行此方法 1513 次。

在这里,我尝试只运行此方法一次。看看做是有效的,以及完成操作需要多少时间。

Stopwatch st = new Stopwatch();
st.Start();
DiagramValue dv = new DiagramValue();
double pixel = dv.CalculateYPixel(23.46, diction);
st.Stop();

当停止秒表告诉我时间是 0.06 秒。

当我在 for 循环中运行相同的方法 1513 次时:

Stopwatch st = new Stopwatch();
st.Start();
for (int i = 0; i < 1513; i++)
{
    DiagramValue dv = new DiagramValue();
    double pixel = dv.CalculateYPixel(23.46, diction);
}
st.Stop();

然后秒表告诉我工作在 0.14 秒左右。或一次 0.14s/1513 次 = 0.00009s。

我的问题是为什么如果我只运行一次某个方法太慢了,如果我在 for 循环中运行数千次几乎是同一时间。

为什么如果我运行一次方法,如果我在循环 c# 中运行几次,几乎同时完成工作

编写基准测试很难。

首先,Stopwatch不是无限准确的。当您只运行一次该方法时,您受到基础秒表准确性的限制。另一方面,多次运行该方法可以缓解此问题 - 您可以通过使用足够大的循环来获得任意精度。而不是 1 与 1513,例如比较 1500 与 3000。正如预期的那样,您将获得大约 100% 的时间增加。

其次,特别是第一次调用(例如 JIT 编译(或调用时的内存压力通常会产生一些成本。这就是为什么您通常需要进行"预热"的原因 - 首先在秒表外部运行该方法以隔离它们,然后再测量(多次调用(。

第三,在像.NET这样的垃圾回收环境中,订购啤酒的人不一定是支付账单的人。.NET 中内存分配的大部分成本都在集合中,而不是分配本身(与堆栈分配一样便宜(。集合通常发生在最初导致分配的代码之外,在搜索性能问题时将您指向完全错误的方向。这就是大多数 .NET 内存跟踪器单独显示垃圾回收的原因 - 考虑这一点很重要,但如果您不小心,很容易误导您原因。

还有更多问题,但这些问题应该足以涵盖您的特定方案。

一些可能的原因包括:

  1. 时序分辨率。当您在大量迭代中找到平均值时,您将获得更准确的数字。

  2. 噪声。不是你真正想要记录的东西的百分比会有所不同。

  3. .NET 将在首次使用方法时创建代码。因此,在程序生命周期中第一次运行时,花费的时间就越长,这是一个很大的因素(尝试运行一次,然后测量第二次尝试(。

  4. 分支预测。如果你继续用相同的数据做同样的事情,CPU的分支预测器将更好地预测哪些分支被占用。

  5. 气相色谱稳定性。在这种情况下不太可能,但有可能。通常在一组需要创建特定对象然后释放的操作开始时,程序最终必须从操作系统中获取更多内存。当它进入这组操作时,它更有可能达到一个稳定的状态,它可以通过清理它不再使用的对象来获取内存,这更快。

相关文章: