【问题标题】:Benchmarking method calls in C# [duplicate]C#中的基准方法调用[重复]
【发布时间】:2009-10-25 23:17:31
【问题描述】:

我正在寻找一种方法来对 C# 中的方法调用进行基准测试。

我已经为大学作业编写了一个数据结构,并且只是想出了一种优化一点的方法,但这种方法会在所有情况下增加一些开销,同时将 O(n) 调用转换为 O (1) 在某些方面。

现在我想针对测试数据运行这两个版本,看看是否值得实施优化。我知道在 Ruby 中,您可以将代码包装在 Benchmark 块中,并让它在控制台中输出执行该块所需的时间 - 是否有类似的东西可用于 C#?

【问题讨论】:

    标签: c# benchmarking


    【解决方案1】:

    从 Yuriy 的回答中窃取(和修改):

    private static void Benchmark(Action act, int iterations)
    {
        GC.Collect();
        act.Invoke(); // run once outside of loop to avoid initialization costs
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            act.Invoke();
        }
        sw.Stop();
        Console.WriteLine((sw.ElapsedMilliseconds / iterations).ToString());
    }
    

    通常,一个特定的方法必须初始化一些东西,而您并不总是希望将这些初始化成本包含在您的整体基准测试中。此外,您希望将总执行时间除以迭代次数,以便您的估计或多或少与迭代次数无关。

    【讨论】:

    • 很好,我只是在寻找一种快速的 C# 基准测试方法。
    • 从您自己的答案中找到了答案? StackOverflow 已经存在足够长的时间了,我也遇到过几次这种情况:过去的我回答了现在我正在问的一个问题。
    • 示例:Benchmark(() =&gt; { /* your code */ }, 100);
    【解决方案2】:

    这是我通过反复试验发现的一些东西。

    1. 丢弃第一批(数千次)迭代。他们很可能会受到 JITter 的影响。
    2. 在单独的Thread 对象上运行基准测试可以提供更好、更稳定的结果。我不知道为什么。
    3. 我见过一些人在执行基准测试之前出于某种原因使用Thread.Sleep。这只会让事情变得更糟。我不知道为什么。可能是由于 JITter。
    4. 切勿在启用调试的情况下运行基准测试。代码很可能会慢几个数量级。
    5. 在启用所有优化的情况下编译您的应用程序。优化可能会严重影响某些代码,而其他代码则不会,因此未经优化的编译会影响基准测试的可靠性。
    6. 在启用优化的情况下进行编译时,有时需要以某种方式评估基准的输出(例如打印值等)。否则编译器可能会“找出”一些计算是无用的,并且根本不会执行它们。
    7. 在执行某些基准测试时,调用委托可能会产生明显的开销。最好在委托中放置多个迭代,这样开销对基准测试的结果影响不大。
    8. 分析器可以有自己的开销。他们擅长告诉您代码的哪些部分是瓶颈,但他们并不擅长可靠地对两个不同的事物进行实际基准测试。
    9. 一般来说,花哨的基准测试解决方案可能会产生明显的开销。例如,如果您想使用一个接口对许多对象进行基准测试,那么将每个对象包装在一个类中可能很诱人。但是,请记住,类构造函数也有必须考虑的开销。最好让一切都尽可能简单直接。

    【讨论】:

      【解决方案3】:

      我从 Jon Skeet 的基准测试方法中窃取了以下大部分内容:

      private static void Benchmark(Action act, int interval)
      {
          GC.Collect();
          Stopwatch sw = Stopwatch.StartNew();
          for (int i = 0; i < interval; i++)
          {
              act.Invoke();
          }
          sw.Stop();
          Console.WriteLine(sw.ElapsedMilliseconds);
      }
      

      【讨论】:

      • 添加本地 GC.Collect() 可能会让您错过影响性能的内存全局分配问题,但它会使本地测量更加准确。
      【解决方案4】:

      您可以使用内置的Stopwatch class 来“提供一组可用于准确测量经过时间的方法和属性。”如果您正在寻找手动方法。不过不确定是否是自动的。

      【讨论】:

      • 秒表并不是 Benchmark 的最佳方式。它使用处理器的寄存器,因此您自己的代码无法使用它。您可以使用和不使用 Stopwatch 对代码进行基准测试,差异高达 3 倍
      【解决方案5】:

      听起来你想要profiler。我本人强烈推荐EQATEC profiler,它是我尝试过的最好的免费软件。与简单的秒表相比,这种方法的好处在于它还提供了某些方法/块的性能细分。

      【讨论】:

        【解决方案6】:

        分析器提供了最好的基准,因为它们可以诊断您的所有代码,但是它们会减慢很多速度。 Profiler 用于查找瓶颈。

        为了优化算法,当您知道瓶颈在哪里时,使用名称字典-->秒表,在运行时跟踪性能关键部分。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-11
          • 2017-02-04
          • 2018-11-11
          • 2011-01-18
          • 1970-01-01
          • 2020-07-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多