優(yōu)化委托的 `DynamicInvoke`

優(yōu)化委托的 DynamicInvoke

Intro

委托方法里有一個(gè) DynamicInvoke 的方法困曙,可以在不清楚委托實(shí)際類型的情況下執(zhí)行委托方法乳蓄,但是用 DynamicInvoke 去執(zhí)行的話會(huì)比直接用 Invoke 的方法會(huì)慢上很多敞斋,差了兩個(gè)數(shù)量級(jí)黄虱,所以在知道委托類型的情況下盡可能使用 Invoke 執(zhí)行疤剑,但有時(shí)候我們并不知道委托的實(shí)際類型砸狞,比如在很多類庫項(xiàng)目中可能并不是強(qiáng)類型的委托

優(yōu)化方法

優(yōu)化方法,直接執(zhí)行委托的對(duì)應(yīng)的方法,DynamicInvoke 實(shí)際也是調(diào)用的對(duì)應(yīng)的方法虹茶,我們?nèi)绻麍?zhí)行調(diào)用對(duì)應(yīng)的方法就可以優(yōu)化

delegate func = (Func<string, string>)str=> "12345";
string paramString = "321";

// Invoke
((Func<string, string>)func).Invoke(paramString);

// DynamicInvoke
func.DynamicInvoke(new object[]{ paramString });

// Method Invoke
func.Method.Invoke(func.Target, new object[]{ paramString });

性能測(cè)試

下面做一個(gè)性能測(cè)試逝薪,測(cè)試代碼如下:

public class DelegateInvokeTest
{
    private readonly Delegate _func, _func1;
    private readonly string parameter;
    private readonly int paramInt;

    public DelegateInvokeTest()
    {
        parameter = "Test";
        paramInt = 1;

        _func = (Func<string, string>)(str => str);
        _func1 = (Func<int, int>)(val => 0);
    }

    [Benchmark(Baseline = true)]
    public object Invoke()
    {
        return ((Func<string, string>)_func).Invoke(parameter);
    }

    [Benchmark]
    public object InvokeBoxing()
    {
        return ((Func<int, int>)_func1).Invoke(paramInt);
    }

    [Benchmark]
    public object DynamicInvoke()
    {
        return _func.DynamicInvoke(parameter);
    }

    [Benchmark]
    public object DynamicInvokeBoxing()
    {
        return _func1.DynamicInvoke(paramInt);
    }

    [Benchmark]
    public object MethodInfoInvoke()
    {
        return _func.Method?.Invoke(_func.Target, new object[] { parameter });
    }

    [Benchmark]
    public object MethodInfoInvokeBoxing()
    {
        return _func1.Method?.Invoke(_func1.Target, new object[] { paramInt });
    }

    [Benchmark]
    public object ReflectInvoke()
    {
        var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(string));
        var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func) as MethodInfo;
        var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func);
        return method?.Invoke(target, new object[] { parameter });
    }

    [Benchmark]
    public object ReflectInvokeBoxing()
    {
        var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(int));
        var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func1) as MethodInfo;
        var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func1);
        return method?.Invoke(target, new object[] { paramInt });
    }
}

測(cè)試結(jié)果如下:

測(cè)試結(jié)果

由上面的結(jié)果,我們可以看出來蝴罪,直接調(diào)用方法的性能雖然還是比 Invoke 慢上好多董济,但是相比 DynamicInvoke 已經(jīng)優(yōu)化 70% 左右,對(duì)于有裝箱操作的性能會(huì)稍差一些要门,比 DynamicInvoke 優(yōu)化可達(dá) 44% 左右虏肾。

Reference

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市欢搜,隨后出現(xiàn)的幾起案子封豪,更是在濱河造成了極大的恐慌,老刑警劉巖炒瘟,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吹埠,死亡現(xiàn)場離奇詭異,居然都是意外死亡疮装,警方通過查閱死者的電腦和手機(jī)缘琅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廓推,“玉大人刷袍,你說我怎么就攤上這事∈苌叮” “怎么了做个?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵鸽心,是天一觀的道長滚局。 經(jīng)常有香客問我,道長顽频,這世上最難降的妖魔是什么藤肢? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮糯景,結(jié)果婚禮上嘁圈,老公的妹妹穿的比我還像新娘。我一直安慰自己蟀淮,他們只是感情好最住,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怠惶,像睡著了一般涨缚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上策治,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天脓魏,我揣著相機(jī)與錄音兰吟,去河邊找鬼。 笑死茂翔,一個(gè)胖子當(dāng)著我的面吹牛混蔼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播珊燎,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惭嚣,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了俐末?” 一聲冷哼從身側(cè)響起料按,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卓箫,沒想到半個(gè)月后载矿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烹卒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年闷盔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旅急。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逢勾,死狀恐怖藐吮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情迫摔,我是刑警寧澤泥从,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布躯嫉,位于F島的核電站,受9級(jí)特大地震影響擂啥,放射性物質(zhì)發(fā)生泄漏帆阳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一离赫、第九天 我趴在偏房一處隱蔽的房頂上張望塌碌。 院中可真熱鬧台妆,春花似錦、人聲如沸接剩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹃两。三九已至,卻和暖如春俊扳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背号坡。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工梯醒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人日麸。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像涕刚,于是被迫代替她去往敵國和親乙帮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容