<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        .NET Core/Framework如何創建委托大幅度提高反射調用的性能詳解

        來源:懂視網 責編:小采 時間:2020-11-27 22:34:53
        文檔

        .NET Core/Framework如何創建委托大幅度提高反射調用的性能詳解

        .NET Core/Framework如何創建委托大幅度提高反射調用的性能詳解:前言 大家都知道反射傷性能,但不得不反射的時候又怎么辦呢?當真的被問題逼迫的時候還是能找到解決辦法的。 反射是一種很重要的技術,然而它與直接調用相比性能要慢很多,因此如何優化反射性能也就成為一個不得不面對的問題。 目前最常見的優化反射性能的方
        推薦度:
        導讀.NET Core/Framework如何創建委托大幅度提高反射調用的性能詳解:前言 大家都知道反射傷性能,但不得不反射的時候又怎么辦呢?當真的被問題逼迫的時候還是能找到解決辦法的。 反射是一種很重要的技術,然而它與直接調用相比性能要慢很多,因此如何優化反射性能也就成為一個不得不面對的問題。 目前最常見的優化反射性能的方

        前言

        大家都知道反射傷性能,但不得不反射的時候又怎么辦呢?當真的被問題逼迫的時候還是能找到解決辦法的。

        反射是一種很重要的技術,然而它與直接調用相比性能要慢很多,因此如何優化反射性能也就成為一個不得不面對的問題。 目前最常見的優化反射性能的方法就是采用委托:用委托的方式調用需要反射調用的方法(或者屬性、字段)。

        為反射得到的方法創建一個委托,此后調用此委托將能夠提高近乎直接調用方法本身的性能。(當然 Emit 也能夠幫助我們顯著提升性能,不過直接得到可以調用的委托不是更加方便嗎?)

        性能對比數據


        ▲ 沒有什么能夠比數據更有說服力(注意后面兩行是有秒數的)

        可能我還需要解釋一下那五行數據的含義:

        1. 直接調用(😏應該沒有什么比直接調用函數本身更有性能優勢的吧)
        2. 做一個跟直接調用的方法功能一模一樣的委托(😮目的是看看調用委托相比調用方法本身是否有性能損失,從數據上看,損失非常小)
        3. 本文重點 將反射出來的方法創建一個委托,然后調用這個委托(🤩看看吧,性能跟直接調差別也不大嘛)
        4. 先反射得到方法,然后一直調用這個方法(😥終于可以看出來反射本身還是挺傷性能的了,50 多倍的性能損失啊)
        5. 緩存都不用,從頭開始反射然后調用得到的方法(😒100 多倍的性能損失了)

        以下是測試代碼,可以更好地理解上圖數據的含義:

        using System;
        using System.Diagnostics;
        using System.Reflection;
        
        namespace Walterlv.Demo
        {
         public class Program
         {
         static void Main(string[] args)
         {
         // 調用的目標實例。
         var instance = new StubClass();
        
         // 使用反射找到的方法。
         var method = typeof(StubClass).GetMethod(nameof(StubClass.Test), new[] { typeof(int) });
         Assert.IsNotNull(method);
        
         // 將反射找到的方法創建一個委托。
         var func = InstanceMethodBuilder<int, int>.CreateInstanceMethod(instance, method);
        
         // 跟被測方法功能一樣的純委托。
         Func<int, int> pureFunc = value => value;
        
         // 測試次數。
         var count = 10000000;
        
         // 直接調用。
         var watch = new Stopwatch();
         watch.Start();
         for (var i = 0; i < count; i++)
         {
         var result = instance.Test(5);
         }
        
         watch.Stop();
         Console.WriteLine($"{watch.Elapsed} - {count} 次 - 直接調用");
        
         // 使用同樣功能的 Func 調用。
         watch.Restart();
         for (var i = 0; i < count; i++)
         {
         var result = pureFunc(5);
         }
        
         watch.Stop();
         Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用同樣功能的 Func 調用");
        
         // 使用反射創建出來的委托調用。
         watch.Restart();
         for (var i = 0; i < count; i++)
         {
         var result = func(5);
         }
        
         watch.Stop();
         Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用反射創建出來的委托調用");
        
         // 使用反射得到的方法緩存調用。
         watch.Restart();
         for (var i = 0; i < count; i++)
         {
         var result = method.Invoke(instance, new object[] { 5 });
         }
        
         watch.Stop();
         Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用反射得到的方法緩存調用");
        
         // 直接使用反射調用。
         watch.Restart();
         for (var i = 0; i < count; i++)
         {
         var result = typeof(StubClass).GetMethod(nameof(StubClass.Test), new[] { typeof(int) })
         ?.Invoke(instance, new object[] { 5 });
         }
        
         watch.Stop();
         Console.WriteLine($"{watch.Elapsed} - {count} 次 - 直接使用反射調用");
         }
        
         private class StubClass
         {
         public int Test(int i)
         {
         return i;
         }
         }
         }
        }

        如何實現

        實現的關鍵就在于 MethodInfo.CreateDelegate 方法。這是 .NET Standard 中就有的方法,這意味著 .NET Framework 和 .NET Core 中都可以使用。

        此方法有兩個重載:

      1. 要求傳入一個類型,而這個類型就是應該轉成的委托的類型
      2. 要求傳入一個類型和一個實例,一樣的,類型是應該轉成的委托的類型
      3. 他們的區別在于前者創建出來的委托是直接調用那個實例方法本身,后者則更原始一些,真正調用的時候還需要傳入一個實例對象。

        拿上面的 StubClass 來說明會更直觀一些:

        private class StubClass
        {
         public int Test(int i)
         {
         return i;
         }
        }

        前者得到的委托相當于 int Test(int i) 方法,后者得到的委托相當于 int Test(StubClass instance, int i) 方法。(在 IL 里實例的方法其實都是后者,而前者更像 C# 中的代碼,容易理解。)

        單獨使用 CreateDelegate 方法可能每次都需要嘗試第一個參數到底應該傳入些什么,于是我將其封裝成了泛型版本,增加易用性。

        using System;
        using System.Linq;
        using System.Reflection;
        using System.Diagnostics.Contracts;
        
        namespace Walterlv.Demo
        {
         public static class InstanceMethodBuilder<T, TReturnValue>
         {
         /// <summary>
         /// 調用時就像 var result = func(t)。
         /// </summary>
         [Pure]
         public static Func<T, TReturnValue> CreateInstanceMethod<TInstanceType>(TInstanceType instance, MethodInfo method)
         {
         if (instance == null) throw new ArgumentNullException(nameof(instance));
         if (method == null) throw new ArgumentNullException(nameof(method));
        
         return (Func<T, TReturnValue>) method.CreateDelegate(typeof(Func<T, TReturnValue>), instance);
         }
        
         /// <summary>
         /// 調用時就像 var result = func(this, t)。
         /// </summary>
         [Pure]
         public static Func<TInstanceType, T, TReturnValue> CreateMethod<TInstanceType>(MethodInfo method)
         {
         if (method == null)
         throw new ArgumentNullException(nameof(method));
        
         return (Func<TInstanceType, T, TReturnValue>) method.CreateDelegate(typeof(Func<TInstanceType, T, TReturnValue>));
         }
         }
        }

        泛型的多參數版本可以使用泛型類型生成器生成,我在 生成代碼,從 <T> 到 <T1, T2, Tn> —— 自動生成多個類型的泛型 - 呂毅 一文中寫了一個泛型生成器,可以稍加修改以便適應這種泛型類。

        總結

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        .NET Core/Framework如何創建委托大幅度提高反射調用的性能詳解

        .NET Core/Framework如何創建委托大幅度提高反射調用的性能詳解:前言 大家都知道反射傷性能,但不得不反射的時候又怎么辦呢?當真的被問題逼迫的時候還是能找到解決辦法的。 反射是一種很重要的技術,然而它與直接調用相比性能要慢很多,因此如何優化反射性能也就成為一個不得不面對的問題。 目前最常見的優化反射性能的方
        推薦度:
        標簽: 委托 net 性能
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 久久免费观看国产精品| 精品亚洲麻豆1区2区3区| 国产成人人综合亚洲欧美丁香花| 亚洲一区免费视频| 亚洲毛片无码专区亚洲乱| 亚洲视频免费观看| 亚洲日本人成中文字幕| 18禁无遮挡无码网站免费| 亚洲欧美成人av在线观看| 免费在线观看亚洲| 久草免费福利在线| 亚洲AV电影院在线观看| 日韩视频在线精品视频免费观看 | 亚洲第一第二第三第四第五第六 | 好吊妞在线成人免费| 久久精品国产亚洲AV未满十八| 亚洲成AⅤ人影院在线观看| 久久久精品国产亚洲成人满18免费网站 | 日本免费高清一本视频| yellow视频免费看| 亚洲va无码va在线va天堂| 16女性下面无遮挡免费| 亚洲av成人无码网站…| 在线亚洲午夜理论AV大片| 无码人妻精品中文字幕免费| 亚洲欧洲国产综合| jjzz亚洲亚洲女人| 免费国产黄网站在线观看视频| 亚洲综合久久精品无码色欲| 国产亚洲精品拍拍拍拍拍| 国产成人免费高清激情明星| 美女视频黄a视频全免费网站色| 亚洲VA成无码人在线观看天堂| 久久WWW免费人成人片| 国产福利免费视频 | 久久99亚洲综合精品首页| 国产a视频精品免费观看| 人人公开免费超级碰碰碰视频| 亚洲精品第一国产综合精品| 无码专区一va亚洲v专区在线 | 日韩在线一区二区三区免费视频 |