【发布时间】:2019-08-24 12:27:13
【问题描述】:
正如this MSDN article 中所解释的,当使用诸如InvokeMember 之类的.NET 反射API 时,由于元数据的缓存,第一次调用比后续调用需要更多的时间来运行。
当我在不使用反射的情况下测试直接方法调用时,我在 Mono 和 .NET 4 上也看到了类似的效果。
第一个数字是操作的结果,'-'后面的第二个数字是这个操作花费的时间,单位是毫秒。我使用 '
300 - 0.192 <--
300 - 0.004
300 - 0.004
-100 - 0.096 <--
-100 - 0.004
-100 - 0.004
这是为什么?我可以理解第一次调用可能会慢一些,但慢 50 倍并不是我所期望的。
附上得到这个结果的源代码。
图书馆
namespace MyClass
{
public class Calculator
{
public int Value1 {get; set;}
public int Value2 {get; set;}
public Calculator()
{
Value1 = 100;
Value2 = 200;
}
public int Add(int val1, int val2)
{
Value1 = val1; Value2 = val2;
return Value1 + Value2;
}
public int Sub(int val1, int val2)
{
Value1 = val1; Value2 = val2;
return Value1 - Value2;
}
}
}
调用这个库的代码
// http://msdn.microsoft.com/en-us/magazine/cc163759.aspx
using System;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using MyClass;
class TestOne
{
static void DirectTest()
{
Stopwatch sw;
Calculator t = new Calculator();
sw = Stopwatch.StartNew();
int value1 = t.Add(100,200);
sw.Stop();
double time1 = sw.Elapsed.TotalMilliseconds;
sw = Stopwatch.StartNew();
int value2 = t.Add(100,200);
sw.Stop();
double time2 = sw.Elapsed.TotalMilliseconds;
sw = Stopwatch.StartNew();
int value3 = t.Add(100,200);
sw.Stop();
double time3 = sw.Elapsed.TotalMilliseconds;
Console.WriteLine("{0} - {1}", value1, time1);
Console.WriteLine("{0} - {1}", value2, time2);
Console.WriteLine("{0} - {1}", value3, time3);
sw = Stopwatch.StartNew();
value1 = t.Sub(100,200);
sw.Stop();
time1 = sw.Elapsed.TotalMilliseconds;
sw = Stopwatch.StartNew();
value2 = t.Sub(100,200);
sw.Stop();
time2 = sw.Elapsed.TotalMilliseconds;
sw = Stopwatch.StartNew();
value3 = t.Sub(100,200);
sw.Stop();
time3 = sw.Elapsed.TotalMilliseconds;
Console.WriteLine("{0} - {1}", value1, time1);
Console.WriteLine("{0} - {1}", value2, time2);
Console.WriteLine("{0} - {1}", value3, time3);
}
static void Main()
{
DirectTest();
DirectTest();
}
}
【问题讨论】:
-
不要认为第一次调用会慢 50 倍,而认为后续调用会快 50 倍。
-
@Travis Gockel:没错,但在某些情况下,您真正关心的是第一次通过。当然有办法解决这个问题。
-
可能是任何情况,很可能是外部 CPU 压力。这只是一个(非常)糟糕的基准。
-
@Henk Holterman:不,不可能是什么,肯定是JIT编译通。
标签: c# .net performance