在进行性能测试时,为什么初始迭代总是比平均值慢



似乎每次我运行性能测试时,在时间稳定之前的前几次迭代中总会有一个"放松"时间。

以下是性能测试代码(在本例中,我正在测试 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

为什么每次我做测试时都有一个缓冲期?

你想看看Eric Lippert关于性能测试的系列

文章

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

为了在 由于抖动代码、加载,可能产生昂贵的启动成本 库和调用静态构造函数,你必须应用一些 仔细考虑您实际测量的内容。

例如,如果您正在为特定目的进行基准测试 分析启动成本,然后您将需要确保 您只测量第一次运行。另一方面,如果你是 对将运行数百万个 许多天的时间,你想知道平均时间 在典型用法中,那么第一次运行的高成本是 无关紧要,因此不应该成为平均值的一部分。是否 是否在您的计时中包含第一次运行取决于您;我的观点 是,您需要认识到第一次运行具有的事实 可能与第二个成本大不相同。

此外,重要的是要注意,不同的抖动会产生不同的 在不同计算机和不同版本的 .NET 上的结果 框架。jit所需的时间可能会有很大差异,数量也可以 在机器代码中生成的优化。上的 jit 编译器 Windows 32 位桌面、Windows 64 位桌面、Silverlight 在 Mac 上运行,以及当您有 XBOX 360 上的 XNA 中的 C# 程序都有可能不同的 性能特征。

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

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

因此,最好

始终忽略第一次(很少;取决于复杂性)迭代,并且在测量平均时间时不要将其计入统计信息。但是,确切的行为取决于数据集的大小、算法的复杂性、数据库使用情况等依赖关系、硬件和许多其他因素。

最新更新