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

时间:2013-10-15 18:23:35

标签: 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);
            }
        }
    }
}

以下是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

为什么每次我测试时都有一个降温期?

2 个答案:

答案 0 :(得分:6)

您想查看Eric Lippert's series on performance tests

  

错误#6:在测量时将第一次运行视为没有特别之处   平均表现。

     

为了在世界上的基准测试中取得好成绩   由于点击代码,加载而导致潜在的昂贵的启动成本   库和调用静态构造函数,你必须应用一些   仔细考虑你实际测量的是什么。

     

例如,如果您是针对特定目的的基准测试   分析启动成本然后你会想要确保   你只测量第一次运行。另一方面,如果你是   基准测试将要运行数百万的服务的一部分   很多天的时间,你想知道平均时间   在典型的使用中,第一次运行的高成本是   不相关,因此不应该成为平均值的一部分。无论你   包括你的时间的第一次运行取决于你;我的观点   是的,你需要认识到第一次运行的事实   可能与第二种成本差异很大。

...

  

此外,重要的是要注意不同的紧张情绪会有所不同   结果在不同的机器和不同版本的.NET上   框架。 jit所花费的时间差异很大,数量也是如此   在机器代码中生成的优化。 jit编译器上   Windows 32位桌面,Windows 64位桌面,Silverlight   在Mac上运行,以及当你拥有一台时运行的“紧凑”抖动   XBOX XNA上的XNA中的C#程序都有可能不同   性能特点。

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

答案 1 :(得分:4)

原因是在第一次迭代期间,大多数数据和代码都没有被缓存 - 在CPU缓存,操作系统缓存,磁盘缓存,数据库缓存等中。在某些执行环境中,如.NET或Java即时编译也扮演着一个角色。第二次和进一步的迭代已经具有其数据和代码存在于高速缓存中的优点,因此通常执行得更快。

因此,始终忽略第一个(少数;取决于复杂性)迭代并且在测量平均时间时不将其计入统计数据是一个好主意。但是,确切的行为取决于数据集的大小,算法的复杂性,数据库使用的依赖性,硬件和许多其他因素。