在进行性能测试时,为什么初始迭代会不断慢于平均值?

Ben*_*enR 2 c# performance performance-testing

似乎每次我进行性能测试时,在时间稳定之前的前几次迭代中始终存在"减速"时间.

这是性能测试代码(在这种情况下,我测试了Lambda和LINQ之间的区别):

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Sandbox
{
    public class Program
    {
        private static long sum = 0;
        private static int count = 0;

        public class Item
        {
            public string name;
            public int id;
        }

        public static void Main(string[] args)
        {
            // START TESTING PARAMETERS
            List<Item> items = new List<Item>();

            for (int i = 0; i < 1000; i++)
            {
                items.Add(new Item
                {
                    id = i,
                    name = "name_" + i.ToString()
                });
            }

            // END TESTING PARAMETERS

            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int j = 0; j < 10; j++)
            {
                for (int i = 0; i < 5000; i++)
                {
                    // START TESTING CODE

                    Item itm = items.Find(x => x.name == "name_" + i.ToString());

                    // END TESTING CODE
                }
                sum += sw.ElapsedMilliseconds;
                count++;
                sw.Restart();
                Console.WriteLine("Average: {0}", sum / count);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是100,000次测试运行的5次迭代的平均结果:

Average: 1023    Average: 1079    Average: 1017    Average: 1147    Average: 1054
Average: 1003    Average: 963     Average: 1001    Average: 1007    Average: 1020
Average: 1009    Average: 926     Average: 951     Average: 958     Average: 966
Average: 972     Average: 908     Average: 927     Average: 934     Average: 936
Average: 946     Average: 896     Average: 922     Average: 919     Average: 918
Average: 931     Average: 889     Average: 926     Average: 910     Average: 907
Average: 919     Average: 883     Average: 916     Average: 903     Average: 899
Average: 911     Average: 880     Average: 908     Average: 898     Average: 893
Average: 904     Average: 877     Average: 902     Average: 894     Average: 899
Average: 899     Average: 874     Average: 909     Average: 891     Average: 894
Average: 895     Average: 873     Average: 926     Average: 889     Average: 890
Average: 898     Average: 871     Average: 937     Average: 886     Average: 887
Average: 898     Average: 869     Average: 944     Average: 884     Average: 907
Average: 894     Average: 868     Average: 938     Average: 882     Average: 921
Average: 891     Average: 868     Average: 934     Average: 881     Average: 923
Average: 889     Average: 867     Average: 929     Average: 880     Average: 919
Average: 887     Average: 866     Average: 925     Average: 884     Average: 916
Average: 885     Average: 866     Average: 931     Average: 892     Average: 912
Average: 889     Average: 865     Average: 927     Average: 902     Average: 909
Average: 891     Average: 870     Average: 924     Average: 907     Average: 917
Run Code Online (Sandbox Code Playgroud)

有什么理由为什么我每次做测试,都有一个降温期?

Jus*_*ony 6

您想看一下Eric Lippert的性能测试系列

错误#6:在测量平均性能时,将第一次运行视为没有什么特别之处.

为了在由于浏览代码,加载库和调用静态构造函数而导致潜在昂贵的启动成本的世界中从基准测试中获得良好结果,您必须仔细考虑您实际测量的内容.

例如,如果您为分析启动成本的特定目的进行基准测试,那么您将需要确保仅测量第一次运行.另一方面,如果您要对多天运行数百万次的服务进行基准测试,并且您希望知道在典型使用中将采用的平均时间,那么第一次运行的高成本是无关紧要的因此不应该成为平均值的一部分.是否包括你的时间的第一次运行取决于你; 我的观点是,你需要认识到第一次运行的成本可能与第二次运行的成本非常不同.

...

此外,重要的是要注意不同的抖动在不同的机器和.NET框架的不同版本中给出不同的结果.jit所花费的时间差异很大,机器代码中生成的优化量也是如此.Windows 32位桌面上的jit编译器,Windows 64位桌面,Mac上运行的Silverlight以及XBOX 360上的XNA中具有C#程序时运行的"紧凑"抖动都具有潜在的不同性能特征.

简而言之,JIT的价格昂贵.除非这是你想要的,否则你不应该将它考虑在你的测试中.这取决于典型的用法.如果你的代码要启动一次并且长时间保持不变,那么就放弃第一次测试,但是如果它主要是开始和停止,那么第一次测试将是重要的.