似乎每次我进行性能测试时,在时间稳定之前的前几次迭代中始终存在“减速”时间。
这是性能测试代码(在这种情况下,我正在测试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
为什么每次我测试时都有一个降温期?
答案 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即时编译也扮演着一个角色。第二次和进一步的迭代已经具有其数据和代码存在于高速缓存中的优点,因此通常执行得更快。
因此,始终忽略第一个(少数;取决于复杂性)迭代并且在测量平均时间时不将其计入统计数据是一个好主意。但是,确切的行为取决于数据集的大小,算法的复杂性,数据库使用的依赖性,硬件和许多其他因素。