算法中的C#性能波动

时间:2017-09-22 15:12:45

标签: c# algorithm performance benchmarking timing

我对算法和性能基准测试比较陌生,但我有几个问题。

我一直在编写一种算法,我希望能够在一次小迭代中处理这种算法,以限制已经苛刻的流程循环的中断。我的目标是每次迭代处理不到1ms,因此具有相当一致的性能似乎非常重要。

不幸的是,在应用过程权重将算法平均值设置为0.5ms之后,我偶尔会实现超过20ms的时间。我注意到数据收集会导致一些问题(我假设它在内存中移动了吗?),我已经解决但仍然会出现一些性能波动。

所以我在这里制定了一个空白的方法。即使在这里,我偶尔会遇到这些高潮。

    public void DoTask()
    {
        for (int i = 0; i < 100000; i++)
        {
            //do nothing
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        DoTask(); //burn

        var watch = new Stopwatch();
        watch.Start();

        double time;
        for (int j = 0; j < 20; j++)
        {
            for (int i = 0; i < 1000; i++)
            {                   
                time = watch.ElapsedTicks;

                DoTask();

                time = watch.ElapsedTicks - time;

                LongestTime = Math.Max(LongestTime, time);

                TotalTime += time;

                Count++;
            }
            double avgTime = TotalTime / Count;

            MessageBox.Show($"Longest time: {ToMs(LongestTime).ToString("#.##")} Avg time: {ToMs(avgTime).ToString("#.##")}");
            TotalTime = 0;
            Count = 0;
            LongestTime = 0;
        }
    }
  

最长时间:13.04平均时间:.01

是什么导致这种情况发生?这是我无法控制的事情吗?

感谢。

1 个答案:

答案 0 :(得分:2)

实际上更多的是Windows问题(或任何支持多任务的操作系统,但不是涵盖所有消费者操作系统的实时操作系统)。所有常规多任务操作系统都为每个线程提供给定线程在没有中断的情况下运行的时间段,并且可能会切换到另一个线程。如果你的步骤执行暂停在中间,有利于Stopwatch测量的其他一些线程时间,那么主要是线程等待继续执行的时间长度(默认情况下在Windows中大约15ms)。

正确测量时间是一项艰巨的任务,通常最好留给专业工具 - 剖面仪。

如果您希望仅使用进程内定时器获得稍微更一致的测量 - 提高运行代码的线程的优先级。这样,线程暂停的机会就会降低,有利于其他线程。

注意:

  • 实时操作系统通常需要执行代码的一些合作以保证不间断的执行时间。另外我不相信有这样的操作系统支持C#。
  • 即使在像MS DOS这样的非多任务操作系统中,您也可以看到类似的随机时间波动,因为操作系统必须处理来自设备(磁盘,键盘,定时器)的中断,因此可以暂停执行主单线程代码对于中断处理代码的持续时间(通常是很短的时间,但问题仍然存在)。
  • .Net代码增加了一些额外的顾虑,因为它必须执行可能在任何时间点发生的垃圾收集(即由于在另一个线程上的分配)。更多信息Fundamentals of Garbage Collection