我正在尝试衡量某些性能,但我偶然发现了一些我拒绝相信的非常违反直觉的结果。也就是说,在调试模式下查询Dictionary<DateTime>
比在发行模式下更快。
显然,该错误必须在我的测量程序中 - 但是在哪里?在这里是:
Dictionary<DateTime, int> d1 = new Dictionary<DateTime, int>();
// fill the dictionary
DateTime now = DateTime.Now;
const int items = 100000;
for (int i = 0; i < items; i++)
{
DateTime item = now.AddSeconds(-i);
d1.Add(item, i);
}
Console.WriteLine("Items ready");
const int calls = 100000000;
DateTime queryDate = DateTime.Now;
// query the dictionary
var stopwatch = Stopwatch.StartNew();
for (int i = 0; i < calls; i++)
{
int j;
if (d1.TryGetValue(queryDate, out j))
{
throw new InvalidOperationException();
}
}
stopwatch.Stop();
Console.WriteLine("{0}ms", stopwatch.ElapsedMilliseconds);
我通过击中CTL-F5启动此控制台应用程序,因此不附加VS。在我的笔记本电脑上,我在发行模式下的调试版本和2200ms(!)大约获得1200ms。
我已检查/尝试的内容:
- 项目设置只是VS 2015的默认设置:"优化代码"已选中以进行发布,但不能进行调试。要复制,只需创建一个新的控制台应用程序项目,然后将代码复制到
Program
中。 - 当我用
int
作为字典的关键类型测量相同的内容时,发行模式 比预期的debug稍快。
请帮助发现我的盲点!
VS2015中新项目的默认设置为"优先32位"。对于此特定的代码,似乎X86抖动表现出色。
根据汉斯·帕克(Hans Passant)的说法:
优化器无法做到改进此代码。可以设置TryGetValue()调用的堆栈框架有两种基本方法。代码生成器通过将参数直接写入堆栈来使用一种方式,即"现代"方式。但是优化器使用另一种方式,使用推送的"旧"方式。效率较低的方法。这是特定于x86抖动的,x64抖动没有这个问题。
的确,切换到64位,发布模式的速度略高于预期。