似乎每次我运行性能测试时,在时间稳定之前的前几次迭代中总会有一个"放松"时间。
以下是性能测试代码(在本例中,我正在测试 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实时编译也起着重要作用。第二次和进一步的迭代已经具有其数据和代码存在于缓存中的优势,因此通常执行得更快。
因此,最好始终忽略第一次(很少;取决于复杂性)迭代,并且在测量平均时间时不要将其计入统计信息。但是,确切的行为取决于数据集的大小、算法的复杂性、数据库使用情况等依赖关系、硬件和许多其他因素。