2

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

这是性能测试代码(在这种情况下,我正在测试 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

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

4

2 回答 2

6

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

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

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

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

...

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

简而言之,JIT'ing 很昂贵。除非这是您想要的,否则您不应将其纳入测试。这取决于典型用法。如果您的代码要启动一次并长时间保持运行,则丢弃第一个测试,但如果它主要是启动和停止,那么第一个测试将很重要。

于 2013-10-15T18:27:59.623 回答
4

原因是在第一次迭代期间,大多数数据和代码没有被缓存——在 CPU 缓存、操作系统缓存、磁盘缓存、数据库缓存等中。在某些执行环境(如 .NET 或 Java)中,即时编译发挥作用, 也。第二次和进一步的迭代已经具有它们的数据和代码存在于缓存中的优势,因此通常执行得更快。

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

于 2013-10-15T18:28:23.847 回答