System.Diagostics.Stopwatch似乎没有显示正确的经过时间

时间:2016-09-27 04:34:50

标签: c# .net

我正在使用System.Diagnostics.Stopwatchmy program中的两个单独操作计时。

程序找到所有素数,直到用户输入数字。

当我给它一个大的输入,例如100,000时,它报告已经完成了两个操作中的每一个,每个操作在3毫秒内完成。我知道我编写的算法非常有效,但我怀疑它只需要3毫秒。

有时,两个操作中的每个操作都需要很长时间,但是随着时间的推移,仍会打印非常少的毫秒数。

这让我怀疑我的分析代码中有什么问题。你能否告诉我秒表是否报告了正确的时间?如果是的话,为什么我有时会看到探测器输出仅在很长一段时间后出现?

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:2)

由于FindPrimesTill仅构建"查询" (IEnumerable)并且此查询仅在调用primesTillN.Count()时执行(或强制立即执行的任何其他方法),您应该在stopwatch.Stop()后移动primesTillN.Count()并且在'我会得到正确的结果。

答案 1 :(得分:1)

我正在编写这个答案,以供我自己参考链接到github代码。

我的初始代码如下:

static void Main(string[] args)
{
    int n = 0;

    Console.WriteLine("This program prints all prime numbers till a number you specify.\n");
    Console.Write("Find primes till which number? ");

    var b = int.TryParse(Console.ReadLine(), out n);
    if (!b) return;

    var stopwatch = new Stopwatch();
    stopwatch.Start();
    var primesTillN = FindPrimesTill(n);
    stopwatch.Stop();
    var millisecondsToFind = stopwatch.ElapsedMilliseconds;
    var numFound = primesTillN.Count();

    Console.WriteLine($"\n{numFound} primes between 1 and {n}. Time taken to find primes: {millisecondsToFind} milliseconds");
    Console.WriteLine("Printing...\n");

    stopwatch.Reset();
    stopwatch.Start();
    primesTillN.Print();
    stopwatch.Stop();
    var millisecondsToPrint = stopwatch.ElapsedMilliseconds;

    Console.WriteLine($"\n\nSTATS:\nTime to find {numFound} primes between 1 to {n}: {millisecondsToFind} milliseconds.");
    Console.WriteLine($"Time taken to print: {millisecondsToFind} milliseconds.\n");

    Console.ReadKey();
}

正如Aleksey正确指出的那样,我的代码中有两个错误:

  1. 由于方法FindPrimesTill返回了一个懒惰评估的IEnumerable<T>,因此秒表只计算构建查询的时间

    static void Main(string [] args) {     ...

    stopwatch.Start();
    var primesTillN = FindPrimesTill(n);
    stopwatch.Stop();
    var millisecondsToFind = stopwatch.ElapsedMilliseconds;
    var numFound = primesTillN.Count();
    
    ...
    

    }

  2. 这两个修复中的一个可以在这里起作用:

    static void Main(string[] args)
    {
        ...
    
        stopwatch.Start();
        var primesTillN = FindPrimesTill(n);
    
        // Put the call to IEnumerable<T>.Count before
        // stopping the stopwatch.
        // Since  Count() is a greedy operator, 
        // it would have executed the query.
        var numFound = primesTillN.Count();
    
        stopwatch.Stop();
        var millisecondsToFind = stopwatch.ElapsedMilliseconds;
    
        ...
    }
    

    或者:

    static void Main(string[] args)
    {
        ...
    
        stopwatch.Start();
    
        // Eagerly evaluate the IEnumerable returned
        // by FindPrimesTill by converting it into a List<T>
        var primesTillN = FindPrimesTill(n).ToList();
        stopwatch.Stop();
        var millisecondsToFind = stopwatch.ElapsedMilliseconds;
    
        var numFound = primesTillN.Count;
        ...
    }
    
    1. 我的代码中的第二个错误是,当我应该在第二个实例中打印出millisecondsToFind以计算millisecondsToPrint方法调用时,我打印出变量IEnumerable<T>.Print

      static void Main(string [] args) {     ...

      Console.WriteLine($"Time taken to print: {millisecondsToFind} milliseconds.\n");
      
      Console.ReadKey();
      

      }

    2. 应该是:

      static void Main(string[] args)
      {
          ...
          Console.WriteLine($"Time taken to print: {millisecondsToPrint} milliseconds.\n");
      
          Console.ReadKey();
      }