Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么后续直接方法调用比第一次调用快得多?_C#_.net_Performance - Fatal编程技术网

C# 为什么后续直接方法调用比第一次调用快得多?

C# 为什么后续直接方法调用比第一次调用快得多?,c#,.net,performance,C#,.net,Performance,如中所述,当使用.NET反射API(如InvokeMember)时,由于元数据的缓存,第一个调用比后续调用运行的时间要长得多 当我在不使用反射的情况下测试direct方法调用时,我在Mono和.NET4上也看到了类似的效果 第一个数字是该操作的结果,“-”之后的第二个数字是该操作在毫秒内花费的时间。我使用了“这是因为.NET应用程序使用的编译方法。JIT编译器会将代码转换为机器代码一次,并且该代码的后续执行速度要快得多,因为已经生成并缓存了本机版本 当您运行代码时,您需要支付一次性的罚款,但是J

如中所述,当使用.NET反射API(如
InvokeMember
)时,由于元数据的缓存,第一个调用比后续调用运行的时间要长得多

当我在不使用反射的情况下测试direct方法调用时,我在Mono和.NET4上也看到了类似的效果

第一个数字是该操作的结果,“-”之后的第二个数字是该操作在毫秒内花费的时间。我使用了“这是因为.NET应用程序使用的编译方法。JIT编译器会将代码转换为机器代码一次,并且该代码的后续执行速度要快得多,因为已经生成并缓存了本机版本


当您运行代码时,您需要支付一次性的罚款,但是JIT编译器也可以对当前体系结构执行优化,如果代码是从一开始就固有的,则无法执行这些优化。但是,您可以通过调用来强制JIT传递

不要认为第一次调用的速度慢了50倍,而要想后续调用的速度快了50倍。@Travis Gockel:是的,但在某些情况下,您真正关心的是第一次传递。当然有很多方法可以解决这个问题。多个副本,包括任何可能的副本,很可能是外部CPU压力。它只是一个(非常)糟糕的基准。@Henk Holterman:不,它不可能是任何东西,它肯定是JIT编译过程。可能是,但不可能是全部答案。在第一个秒表之前调用这些方法很容易测试。@Henk Holterman:“不可能是全部答案。”-为什么?你还有什么建议?对我来说,这就像是JIT通行证。你还有其他建议吗?@Henk Holterman:嗯,我可以看到他的代码,所以我们知道那里没有线程问题。当然,Windows不是RTOS,但这些数字不会说谎,而且非常可重复。调度问题不会导致如此大的差异,除非机器完全受CPU限制,在这种情况下,我们不会看到如此可重复的数字。我花了相当多的时间在运行.NET应用程序中的CPU瓶颈,我在这里没有看到任何迹象表明这只是第一次JIT传递的结果。你是否也在对双线方法的单次调用周围放置秒表?@Henk Holterman:这会有什么区别?如果有任何问题,代码将以秒表分辨率的速度执行,但鉴于
.194ms
结果,这里的情况并非如此。
300 - 0.192 <--
300 - 0.004
300 - 0.004
-100 - 0.096 <--
-100 - 0.004
-100 - 0.004
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();
    }
}