微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

正如在 this MSDN article中所解释的,当使用诸如InvokeMember之类的.NET Reflection API时,由于元数据的缓存,第一次调用比后续调用花费更多的时间.

当我在不使用Reflection的情况下测试直接方法调用时,我也看到了对Mono和.NET 4的类似效果.

一个数字是操作的结果,“ – ”后面的第二个数字是以ms为单位的此操作所花费的时间.我使用’< - '标记来标识第一个方法调用.

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}",time3);
    }
    static void Main()
    {
        Directtest();
        Directtest();
    }
}

解决方法

这是因为用于.NET应用程序的 Just In Time (JIT)编译方法. J001编译器将 MSIL bytecode转换为机器代码,并且后续执行该代码的速度要快得多,因为已生成并缓存了本机版本.

运行代码时,您需要支付一次罚款,但JIT编译器还可以对当前体系结构执行优化,如果代码是从一开始就是本机代码,则无法执行该优化.但是,您可以通过调用RuntimeHelpers.PrepareMethod.强制执行JIT传递

原文地址:https://www.jb51.cc/csharp/93510.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐