Class 創建性能大比拼(反射,泛型反射,泛型創建,緩存Emit,非緩存Emit)

  一說到反射,很多人都想到了性能,更有甚者直接說“慎用反射,遺患無窮”,“用反射,感覺怎么像是退步啊~”,看到這種言論,直接把反射妖魔化了,如果這種言論長此以往,勢必會對很多對反射初學者造成負面影響。反射是一把雙刃劍,看你怎樣使用了,下面我就用代碼說話。

class TestEntity { }

  1. 手工創建TestEntity?

[TestInfo(Category = "Class.Constructor", Name = "Direct")]
class DirectInvokeMode:IRunable
{
public void Run()
{
new TestEntity();
}
}

?? ? 2. 反射創建TestEntity?

[TestInfo(Category = "Class.Constructor", Name = "Reflect")]
class ReflectInvokeMode : IRunable
{
public void Run()
{
Activator.CreateInstance(
typeof(TestEntity));
}
}

  3. 泛型反射創建TestEntity

[TestInfo(Category = "Class.Constructor", Name = "GenericReflect")]
class GenericReflectInvokeMode : IRunable
{
public void Run()
{
Activator.CreateInstance
<TestEntity>();
}
}

  4. Generic 直接創建

[TestInfo(Category = "Class.Constructor", Name = "Generic Create")]
class GenericCreateInvokeMode : IRunable
{
public void Run()
{
Create
<TestEntity>();
}

static T Create<T>() where T : new()
{
return new T();
}
}
5. Emit創建
[TestInfo(Category = "Class.Constructor", Name = "Emit")]
class EmitInvokeMode : IRunable
{
static readonly ConstructorHandler Ctor = typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator();

public void Run()
{
Ctor();
}
}

  6. 不緩存Emit的創建

[TestInfo(Category = "Class.Constructor", Name = "NoCacheEmit")]
class NoCacheEmitInvokeMode : IRunable
{
public void Run()
{
typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator()();
}
}

  測試程序:(執行10萬次創建Class對象)

foreach (var item in Mappers)
CodeTimer.Time(item.Metadata.Category
+ "->" + item.Metadata.Name, 100000, () => item.Value.Run());

輸出結果:

------ Test started: Assembly: NLite.Test.dll ------


Class.Constructor
->Direct
Time Elapsed: 5ms
CPU Cycles:
0
Gen
0: 1
Gen
1: 0
Gen
2: 0

Class.Constructor
->Reflect
Time Elapsed: 320ms
CPU Cycles:
2,968,750
Gen
0: 1
Gen
1: 0
Gen
2: 0

Class.Constructor
->GenericReflect
Time Elapsed: 147ms
CPU Cycles:
1,250,000
Gen
0: 1
Gen
1: 0
Gen
2: 0

Class.Constructor
->Generic Create
Time Elapsed: 159ms
CPU Cycles:
1,406,250
Gen
0: 1
Gen
1: 0
Gen
2: 0

Class.Constructor
->Emit
Time Elapsed: 6ms
CPU Cycles:
0
Gen
0: 2
Gen
1: 0
Gen
2: 0

Class.Constructor
->NoCacheEmit
Time Elapsed:
12,786ms
CPU Cycles:
119,218,750
Gen
0: 162
Gen
1: 81
Gen
2: 0

1 passed, 0 failed, 0 skipped, took 67.77 seconds (NUnit 2.5.5).

  性能比較結果應該是一目了然了!

?? ? ?附上源代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.Reflection;
using NLite.Reflection;namespace NLite.Test.Reflection
{[Contract]public interface IRunable{void Run();}//測試器元數據public interface ITestInfo{//目錄string Category { get; }//名稱string Name { get; }}//映射器元數據注解[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)][MetadataAttributeAttribute]public class TestInfoAttribute : ComponentAttribute{public string Category { get; set; }public string Name { get; set; }}[TestFixture]public class SpecBase{public SpecBase(){}[SetUp]public void SetUp(){Given();When();}public virtual void Given() { }public virtual void When(){}[Test]public void Test(){}}public abstract class PerformanceSpecBase : SpecBase{[InjectMany]protected Lazy<IRunable, ITestInfo>[] Mappers;protected abstract void RegisterComponents();public virtual int Times{get { return 100000; }}public override void Given(){RegisterComponents();ServiceRegistry.Compose(this);}public override void When(){for (int i = 0; i < 3; i++){foreach (var item in Mappers)CodeTimer.Time(item.Metadata.Category + "->" + item.Metadata.Name, Times, () => item.Value.Run());}}}public class InvokeConstructorPerformanceSpec : PerformanceSpecBase{class TestEntity { }protected override void RegisterComponents(){ServiceRegistry.Register<DirectInvokeMode>().Register<ReflectInvokeMode>().Register<GenericReflectInvokeMode>().Register <GenericCreateInvokeMode>().Register<EmitInvokeMode>().Register < NoCacheEmitInvokeMode>().Register < GenericReflectInvokeMode2>();}[TestInfo(Category = "Class.Constructor", Name = "Direct")]class DirectInvokeMode:IRunable{public void Run(){new TestEntity();}}[TestInfo(Category = "Class.Constructor", Name = "Reflect")]class ReflectInvokeMode : IRunable{public void Run(){Activator.CreateInstance(typeof(TestEntity));}}[TestInfo(Category = "Class.Constructor", Name = "GenericReflect")]class GenericReflectInvokeMode : IRunable{public void Run(){Activator.CreateInstance<TestEntity>();}}[TestInfo(Category = "Class.Constructor", Name = "Reflect->Reflect")]class GenericReflectInvokeMode2 : IRunable{static readonly MethodInfo CreateMethod = typeof(Activator).GetMethod("CreateInstance", Type.EmptyTypes).MakeGenericMethod(typeof(TestEntity));public void Run(){CreateMethod.Invoke(null,null);}}[TestInfo(Category = "Class.Constructor", Name = "Generic Create")]class GenericCreateInvokeMode : IRunable{public void Run(){Create<TestEntity>();}static T Create<T>() where T : new(){return new T();}}[TestInfo(Category = "Class.Constructor", Name = "Emit")]class EmitInvokeMode : IRunable{static readonly ConstructorHandler Ctor = typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator();public void Run(){Ctor();}}[TestInfo(Category = "Class.Constructor", Name = "NoCacheEmit")]class NoCacheEmitInvokeMode : IRunable{public void Run(){typeof(TestEntity).GetConstructor(Type.EmptyTypes).GetCreator()();}}}}

?? ? ?最后給大家一個思考題:Struct 創建性能大比拼的結果是怎樣的?(注意Struct是值類型,Class是引用類型,值類型是分配在棧上的,引用類型是分配在堆上的)

轉載于:https://www.cnblogs.com/netcasewqs/archive/2011/04/18/2019999.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275533.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275533.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275533.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

es6沖刺01

1、let/const 1)作用域&#xff1a;es5中有全局作用域、函數作用域。es6中新增了塊級作用域 2&#xff09;let定義的變量在所在塊級作用域外失效&#xff0c;嚴格模式下失效后直接報錯&#xff0c; 且不允許重復聲明同名變量 3)const用于聲明常量&#xff0c;聲明時必須賦值&am…

linux網卡固件名,修改CentOS7網卡名稱為傳統名稱eth0格式

使用CentOS7以前系統的小伙伴裝完CentOS7以后發現了一個問題&#xff0c;那就是網卡名改變為了“en016777736”&#xff0c;而不是以前的eth0的簡易模式了&#xff0c;如圖&#xff1a;以往的CentOS7以前的系統網卡命名雖然簡單方便&#xff0c;但也會帶來一些問題&#xff0c;…

Baymard Institute:基于UX的最佳實踐的光榮的,循證的工具

重點 (Top highlight)I realized I wanted to write this piece when I mentioned the Baymard Institute to a User Researcher with 10 years of experience and they had no idea what I was talking about. They aren’t alone! I’ve gotten plenty of raised eyebrows on…

Vue 3.2 發布了,那尤雨溪是怎么發布 Vue.js 的?

1. 前言大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12&#xff0c;長期交流學習。之前寫的《學習源碼整體架構系列》 包含jQuery、underscore、lodash、vuex、sentry、axios、redux、koa、vue-devtools、vuex4十篇源碼文章。…

wireshark使用教程 linux,Linux入門教程:ubuntu下安裝wireshark(以及配置非root),這個強大的工具可以捕...

Linux入門教程:ubuntu下安裝wireshark(以及配置非root),這個強大的工具可以捕Wireshark是世界上最流行的網絡分析工具。這個強大的工具可以捕捉網絡中的數據&#xff0c;并為用戶提供關于網絡和上層協議的各種信息。與很多其他網絡工具一樣&#xff0c;Wireshark也使用pcap net…

IronPython和C#執行速度對比

其實我自己對執行速度這個問題本來并沒有什么興趣&#xff0c;因為以前的經驗告訴我&#xff1a;除非是運算密集型的程序&#xff0c;否則腳本語言和編譯型語言使用起來速度沒有多大差別。但是我們公司有個人知道我的想法以后&#xff0c;天天在我耳邊嚷嚷腳本運行速度太慢&…

基于超級賬本Fabric的供應鏈跟蹤解決方案【開源】

2019獨角獸企業重金招聘Python工程師標準>>> 本項目為基于Hyperledger Fabric區塊鏈的供應鏈資產跟蹤解決方案&#xff0c;項目主要包括鏈碼和Web應用兩部分。Fabric鏈碼采用GOLANG開發&#xff0c;負責維護資產的狀態&#xff0c;后臺為采用Node.js開發的Web應用&a…

同理心案例及故事分享_神經形態,視覺可及性和同理心

同理心案例及故事分享“A good UX designer has empathy”.“優秀的UX設計人員具有同理心”。 This is something every UX designer has heard at some point in their career. Empathy helps us get into the mindset of the user and build solutions that solve real probl…

純CSS實現beautiful按鈕

大家好&#xff0c;我是若川。邀你進源碼共讀群學習交流。今天分享一篇好文。可收藏&#xff5e;近期工作中遇到一個需求——實現一些酷炫的按鈕&#xff0c;看到效果圖之后&#xff0c;按鈕確實漂亮&#xff0c;有彈跳、顏色漸變、掃光、霓虹燈&#xff0c;瞬間激起了我的好奇…

linux的內核有多小,Linux 內核有小bug?

今天讀著讀著Linux代碼&#xff0c;竟然無意中發現Linux 0.11內核有個小bug&#xff0c;呵呵&#xff0c;人非圣賢孰能無過。// 在目錄項數據塊中搜索匹配指定文件名的目錄項&#xff0c;首先讓de 指向數據塊&#xff0c;并在不超過目錄中目錄項數// 的條件下&#xff0c;循環執…

菜單窗口_菜單

菜單窗口The Hamburger Menu widget is on every other site nowadays. It has become synonymous with the web and, perhaps even more so, with web development. Have, for instance, a look at Dribbble or Codepen. There you’ll find a fair share of examples. They c…

帝國cms 打開打開轉換表文件失敗!

帝國cms 升級到最新版6.6 后 生成列表頁面和 搜索 時出現 “打開打開轉換表文件失敗&#xff01;” 跟蹤文件找到 include($file); 這行代碼時出錯非常納悶&#xff0c;這個是php的內部命令啊&#xff0c;跟帝國的編碼應該沒有關系一直沒有再往下細找&#xff0c;只好根據錯誤提…

怎么在PDF上修改文字,PDF修改文字的步驟

怎么在PDF文件上修改文字呢&#xff1f;其實現在的很多的PDF文件上會出現文字錯誤的情況&#xff0c;想要修改PDF文件上面的文字卻不知道怎么修改&#xff0c;想要修改PDF文件還是比較簡單的&#xff0c;使用專業的PDF編輯器就可以進行操作了&#xff0c;下面小編就為大家分享一…

linux raw限制端口訪出,使用Linux raw socket時需要注意的一些問題

本文的copyleft歸gfree.windgmail.com所有&#xff0c;使用GPL發布&#xff0c;可以自由拷貝&#xff0c;轉載。但轉載請保持文檔的完整性&#xff0c;注明原作者及原鏈接&#xff0c;嚴禁用于任何商業用途。作者&#xff1a;gfree.windgmail.com博客&#xff1a;linuxfocus.bl…

讀完 Vue 發布源碼,小姐姐回答了 leader 的提問,并優化了項目發布流程~

大家好&#xff0c;我是若川。這是 源碼共讀 第三期活動&#xff0c;紀年小姐姐的第三次投稿。紀年小姐姐學習完優化了自己的項目發布流程&#xff0c;而且回答了leader對她的提問&#xff0c;來看看她的思考和實踐。第三期是 Vue 3.2 發布了&#xff0c;那尤雨溪是怎么發布 Vu…

小程序背景圖片的坑

本人是前端菜鳥一個&#xff0c;比小白還要白&#xff0c;這完全是自己的經驗總結&#xff0c;并不是要給各位分享什么寶貴經驗哈&#xff0c;各位大佬不喜勿噴&#xff0c;不然會打擊到我的哈哈因為公司要求做幾個小程序的頁面&#xff0c;我不得不拾起丟棄了幾個月的小程序開…

SimpleAdapter類使用方法

SimpleAdapter的構造函數是&#xff1a; public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) 官方說明了其各個參數含義&#xff0c;我這里根據自己的理解解釋下&#xff1a; 第一個context&…

小程序 富文本自適應屏幕_自適應文本:跨屏幕尺寸構建可讀文本

小程序 富文本自適應屏幕Many of you may already know about responsive web design. Cited from Wikipedia, responsive web design (RWD) is an approach to web design that makes web pages render well on a variety of devices and windows or screen sizes. The respon…

Vue、React 之間如何實現代碼移植?

大家好&#xff0c;我是若川。面對前端最火的兩個框架&#xff0c;學 React 還是 Vue &#xff1f;這可能是每個前端人都曾糾結過的問題。不過&#xff0c;現在你不用糾結了——因為很多公司都是兩個框架都有大量的應用&#xff0c;取決于不同團隊的技術選型&#xff0c;特別是…

linux mariadb 亂碼,配置mariadb遠程訪問權限,解決數據庫亂碼問題

配置mariadb遠程訪問權限&#xff1a;1)登錄數據庫:# mysql -uroot -p2)配置授權數據庫用戶遠程訪問權限&#xff0c;%表示所有遠程IP&#xff0c;也可以指定IP。WITH GRANT OPTION表示mysql數據庫的grant表中重新加載權限數據&#xff1a;GRANT ALL PRIVILEGES ON *.* TO 用戶…