C# C中的基准方法调用#

C# C中的基准方法调用#,c#,benchmarking,C#,Benchmarking,我正在寻找一种在C#中对方法调用进行基准测试的方法 我已经为大学作业编写了一个数据结构,并且刚刚提出了一种优化一点的方法,但是在所有情况下都会增加一点开销,同时在某些情况下会将O(n)调用转换为O(1) 现在我想对测试数据运行这两个版本,看看是否值得实现优化。我知道,在Ruby中,您可以将代码包装在基准块中,并让它在控制台中输出执行该块所需的时间-是否有类似于C#?的功能,您可以使用内置功能“提供一组方法和属性,您可以使用这些方法和属性精确测量经过的时间。”如果你正在寻找一种手动方式来做这件事。

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

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


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

的功能,您可以使用内置功能“提供一组方法和属性,您可以使用这些方法和属性精确测量经过的时间。”如果你正在寻找一种手动方式来做这件事。但不确定是否自动。

听起来你想要一个。我强烈推荐我自己,这是我试过的最好的免费的。与简单的秒表方法相比,这种方法的优点在于它还提供了某些方法/块的性能细分。

我从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);
}
private静态无效基准测试(Action-act,int-interval)
{
GC.Collect();
秒表sw=Stopwatch.StartNew();
对于(int i=0;i
探查器提供了最好的基准测试,因为它们可以诊断所有代码,但会大大降低速度。分析器用于查找瓶颈

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

从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());
}
私有静态void基准测试(Action act,int迭代)
{
GC.Collect();
act.Invoke();//在循环外运行一次以避免初始化成本
秒表sw=Stopwatch.StartNew();
对于(int i=0;i

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

以下是我通过尝试和错误发现的一些东西

  • 放弃第一批(数千)迭代。它们很可能会受到抖动的影响
  • 在单独的
    线程
    对象上运行基准测试可以提供更好、更稳定的结果。我不知道为什么
  • 我见过一些人在执行基准测试之前出于任何原因使用
    Thread.Sleep
    。这只会让事情变得更糟。我不知道为什么。可能是因为抖动
  • 永远不要在启用调试的情况下运行基准测试。代码运行速度很可能要慢几个数量级
  • 在启用所有优化的情况下编译应用程序。有些代码可能会受到优化的严重影响,而其他代码则不会,因此在不进行优化的情况下编译会影响基准测试的可靠性
  • 在启用优化的情况下编译时,有时需要以某种方式评估基准测试的输出(例如打印值等)。否则,编译器可能会“发现”某些计算是无用的,并且不会执行它们
  • 在执行某些基准测试时,调用委托可能会有明显的开销。最好在委托中放置多个迭代,这样开销对基准测试的结果影响不大
  • 探查器可以有自己的开销。他们擅长告诉您代码的哪些部分是瓶颈,但他们并不擅长可靠地对两种不同的东西进行基准测试
  • 一般来说,奇特的基准测试解决方案可能会有明显的开销。例如,如果您希望使用一个接口对多个对象进行基准测试,那么很可能会将每个对象包装到一个类中。但是,请记住,类构造函数也有必须考虑的开销。最好让一切尽可能简单直接

  • 添加local GC.Collect()可能会使您错过影响性能的内存全局分配问题,但它会使本地测量更准确。很好,我只是在搜索一种快速的C#基准测试方法。并从您自己的答案中找到了一个答案?StackOverflow已经存在足够长的时间了,现在我身上已经发生过几次了:过去的我回答了现在的我正在问的一个问题秒表不是最好的基准测试方法。它使用处理器的寄存器,所以您自己的代码不能使用它。您可以使用秒表对代码进行基准测试,也可以不使用秒表对代码进行基准测试,其差异高达3倍