西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴(lài)的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)編程開(kāi)發(fā)C#.NET → .Net中各種不同的對(duì)象創(chuàng)建方式的速度差異(三)

.Net中各種不同的對(duì)象創(chuàng)建方式的速度差異(三)

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:tonyhuang時(shí)間:2010/2/24 14:49:30字體大。A-A+

作者:佚名點(diǎn)擊:107次評(píng)論:0次標(biāo)簽: 對(duì)象創(chuàng)建

  • 類(lèi)型:系統(tǒng)其它大。2.2M語(yǔ)言:中文 評(píng)分:10.0
  • 標(biāo)簽:
立即下載

從前面的文章,我們發(fā)現(xiàn)以下兩點(diǎn)有趣的東西:

1、使用System.Activator的非泛型方法比使用泛型方法快很多(超過(guò)200%)
2、使用泛型約束和new關(guān)鍵字創(chuàng)建的速度幾乎和System.Activator的泛型方法的一樣
在這篇文章里,我將會(huì)這兩個(gè)問(wèn)題做一個(gè)進(jìn)一步的探究,我使用的工具就是鼎鼎大名的.Net反編譯工具:Reflector,歡迎讀者跟我一起探討造成這個(gè)現(xiàn)象的原因。
第一段 從System.Activator.CreateInstance(Type)開(kāi)始
我們先用Reflector打開(kāi).Net Framework 3.5中的mscorlib.dll,看看這里面,微軟是怎么實(shí)現(xiàn)的。
首先看看System.Activator.CreateInstance(Type),它直接調(diào)用了System.Activator.CreateInstance(Type, Boolean),代碼如下

1 public static object CreateInstance(Type type)

2 {

3 return CreateInstance(type, false);

4 }

那么這個(gè)CreateInstance(Type, Boolean)的實(shí)現(xiàn),是這樣的:

01 public static object CreateInstance(Type type, bool nonPublic)

02 {

03 if (type == null)

04 {

05 throw new ArgumentNullException("type");

06 }

07 RuntimeType underlyingSystemType = type.UnderlyingSystemType as RuntimeType;

08 if (underlyingSystemType == null)

09 {

10 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type");

11 }

12 return underlyingSystemType.CreateInstanceImpl(!nonPublic);

13 }

將這段代碼簡(jiǎn)化一下,就是:

1 public static object CreateInstance(Type type, bool nonPublic)

2 {

3 RuntimeType underlyingSystemType = type.UnderlyingSystemType as RuntimeType;

4 return underlyingSystemType.CreateInstanceImpl(!nonPublic);

5 }

在RuntimeType的CreateInstanceImpl(bool isPublic)中,直接調(diào)用了CreateInstanceImpl(bool isPublic, bool skipVisibilityCheck, bool fillCache),這個(gè)函數(shù)的實(shí)現(xiàn)非常有意思,我先把代碼貼出來(lái):

01 internal object CreateInstanceImpl(bool publicOnly, bool skipVisibilityChecks, bool fillCache)

02 {

03 RuntimeTypeHandle typeHandle = this.TypeHandle;

04 ActivatorCache cache = s_ActivatorCache;

05 if (cache != null)

06 {

07 ActivatorCacheEntry entry = cache.GetEntry(this);

08 if (entry != null)

09 {

10 if ((publicOnly && (entry.m_ctor != null)) && ((entry.m_hCtorMethodHandle.GetAttributes() & MethodAttributes.MemberAccessMask) != MethodAttributes.Public))

11 {

12 throw new MissingMethodException(Environment.GetResourceString("Arg_NoDefCTor"));

13 }

14 object obj2 = typeHandle.Allocate();

15 if (entry.m_ctor != null)

16 {

17 if (!skipVisibilityChecks && entry.m_bNeedSecurityCheck)

18 {

19 MethodBase.PerformSecurityCheck(obj2, entry.m_hCtorMethodHandle, this.TypeHandle.Value, 0x10000000);

20 }

21 try

22 {

23 entry.m_ctor(obj2);

24 }

25 catch (Exception exception)

26 {

27 throw new TargetInvocationException(exception);

28 }

29 }

30 return obj2;

31 }

32 }

33 return this.CreateInstanceSlow(publicOnly, fillCache);

34 }

看起來(lái)非常復(fù)雜,其實(shí)他的實(shí)現(xiàn)也也就實(shí)現(xiàn)了一個(gè)緩存機(jī)制:

檢查緩存中是否存在這個(gè)構(gòu)造器的委托,如果有,就調(diào)用自己的typeHandler的Allocate()方法分配內(nèi)存,然后調(diào)用構(gòu)造器的委托初始化對(duì)象
如果沒(méi)有緩存,就調(diào)用CreateInstanceSlow(bool isPublic, bool fillCache)創(chuàng)建對(duì)象,并填充緩存
好吧繼續(xù)再看看這個(gè)CreateInstanceSlow里面干了什么事情。
照例先貼代碼吧:

01 private object CreateInstanceSlow(bool publicOnly, bool fillCache)

02 {

03 RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle;

04 bool bNeedSecurityCheck = true;

05 bool canBeCached = false;

06 bool noCheck = false;

07 this.CreateInstanceCheckThis();

08 if (!fillCache)

09 {

10 noCheck = true;

11 }

12 object obj2 = RuntimeTypeHandle.CreateInstance(this, publicOnly, noCheck, ref canBeCached, ref emptyHandle, ref bNeedSecurityCheck);

13 if (canBeCached && fillCache)

14 {

15 ActivatorCache cache = s_ActivatorCache;

16 if (cache == null)

17 {

18 cache = new ActivatorCache();

19 Thread.MemoryBarrier();

20 s_ActivatorCache = cache;

21 }

22 ActivatorCacheEntry ace = new ActivatorCacheEntry(this, emptyHandle, bNeedSecurityCheck);

23 Thread.MemoryBarrier();

24 cache.SetEntry(ace);

25 }

26 return obj2;

27 }

這個(gè)函數(shù)寫(xiě)的很復(fù)雜,其實(shí)實(shí)現(xiàn)的東西很簡(jiǎn)單,其一是調(diào)用RuntimeTypeHandler.CreateInstance方法創(chuàng)建對(duì)象,然后再填充緩存,以加快下次創(chuàng)建對(duì)象的速度。
好了,我們現(xiàn)在已經(jīng)非常接近事實(shí)的真相了。讓我們從另外一個(gè)角度出發(fā),看看CreateInstance()干了什么事情。
第二段 從System.Activator.CreateInstance()開(kāi)始
這里,我們先看看他的實(shí)現(xiàn):

1 public static T CreateInstance<T>()

2 {

3 bool bNeedSecurityCheck = true;

4 bool canBeCached = false;

5 RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle;

6 return (T) RuntimeTypeHandle.CreateInstance(typeof(T) as RuntimeType, true, true, ref canBeCached, ref emptyHandle, ref bNeedSecurityCheck);

7 }

我們忽然就看到了我們熟悉的身影:RuntimeTypeHandler.CreateInstance方法,終于殊途同歸啊。。。
也就是說(shuō),System.Activator.CreateInstance()相當(dāng)于調(diào)用了CreateInstanceSlow方法(但是沒(méi)有緩存機(jī)制),這應(yīng)該就是CreateInstance比CreateInstance(Type)慢的主要原因,我們回顧一下這兩個(gè)方法的時(shí)間消耗:
System.Activator.CreateInstance(Type):

緩存機(jī)制時(shí)間消耗
RuntimeTypeHandler.Allocate()內(nèi)存分配的時(shí)間消耗
調(diào)用構(gòu)造器委托初始化數(shù)據(jù)的時(shí)間消耗
這里不考慮緩存失敗,調(diào)用CreateInstanceSlow的情況,因?yàn)檫@個(gè)只會(huì)發(fā)生一次。
System.Activator.CreateInstance(Type):

調(diào)用RuntimeTypeHandler.CreateInstance的時(shí)間消耗
在下一篇文章中,我會(huì)對(duì)這兩個(gè)函數(shù)的性能差異做進(jìn)一步的分析

 

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀(guān)圍觀(guān)
    • 2 無(wú)聊無(wú)聊

    熱門(mén)評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱(chēng):
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)