• <td id="ae6ms"><li id="ae6ms"></li></td>
  • <xmp id="ae6ms"><td id="ae6ms"></td><table id="ae6ms"></table>
  • <table id="ae6ms"></table>
  • <td id="ae6ms"></td>
    <td id="ae6ms"></td>
  • <table id="ae6ms"></table><table id="ae6ms"><td id="ae6ms"></td></table>
  • <td id="ae6ms"></td>
  • <table id="ae6ms"><li id="ae6ms"></li></table>
  • <table id="ae6ms"></table>
    西西軟件園多重安全檢測下載網站、值得信賴的軟件下載站!
    軟件
    軟件
    文章
    搜索

    首頁編程開發C#.NET → .Net中各種不同的對象創建方式的速度差異(三)

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

    相關軟件相關文章發表評論 來源:tonyhuang時間:2010/2/24 14:49:30字體大?。?em class="fontsize">A-A+

    作者:佚名點擊:107次評論:0次標簽: 對象創建

    • 類型:系統其它大?。?i>2.2M語言:中文 評分:10.0
    • 標簽:
    立即下載

    從前面的文章,我們發現以下兩點有趣的東西:

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

    1 public static object CreateInstance(Type type)

    2 {

    3 return CreateInstance(type, false);

    4 }

    那么這個CreateInstance(Type, Boolean)的實現,是這樣的:

    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 }

    將這段代碼簡化一下,就是:

    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)中,直接調用了CreateInstanceImpl(bool isPublic, bool skipVisibilityCheck, bool fillCache),這個函數的實現非常有意思,我先把代碼貼出來:

    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 }

    看起來非常復雜,其實他的實現也也就實現了一個緩存機制:

    檢查緩存中是否存在這個構造器的委托,如果有,就調用自己的typeHandler的Allocate()方法分配內存,然后調用構造器的委托初始化對象
    如果沒有緩存,就調用CreateInstanceSlow(bool isPublic, bool fillCache)創建對象,并填充緩存
    好吧繼續再看看這個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 }

    這個函數寫的很復雜,其實實現的東西很簡單,其一是調用RuntimeTypeHandler.CreateInstance方法創建對象,然后再填充緩存,以加快下次創建對象的速度。
    好了,我們現在已經非常接近事實的真相了。讓我們從另外一個角度出發,看看CreateInstance()干了什么事情。
    第二段 從System.Activator.CreateInstance()開始
    這里,我們先看看他的實現:

    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方法,終于殊途同歸啊。。。
    也就是說,System.Activator.CreateInstance()相當于調用了CreateInstanceSlow方法(但是沒有緩存機制),這應該就是CreateInstance比CreateInstance(Type)慢的主要原因,我們回顧一下這兩個方法的時間消耗:
    System.Activator.CreateInstance(Type):

    緩存機制時間消耗
    RuntimeTypeHandler.Allocate()內存分配的時間消耗
    調用構造器委托初始化數據的時間消耗
    這里不考慮緩存失敗,調用CreateInstanceSlow的情況,因為這個只會發生一次。
    System.Activator.CreateInstance(Type):

    調用RuntimeTypeHandler.CreateInstance的時間消耗
    在下一篇文章中,我會對這兩個函數的性能差異做進一步的分析

     

      相關評論

      閱讀本文后您有什么感想? 已有人給出評價!

      • 8 喜歡喜歡
      • 3 頂
      • 1 難過難過
      • 5 囧
      • 3 圍觀圍觀
      • 2 無聊無聊

      熱門評論

      最新評論

      發表評論 查看所有評論(0)

      昵稱:
      表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
      字數: 0/500 (您的評論需要經過審核才能顯示)
      女人让男人桶30分钟免费视频,女人张开腿让男人桶个爽,一进一出又大又粗爽视频
    • <td id="ae6ms"><li id="ae6ms"></li></td>
    • <xmp id="ae6ms"><td id="ae6ms"></td><table id="ae6ms"></table>
    • <table id="ae6ms"></table>
    • <td id="ae6ms"></td>
      <td id="ae6ms"></td>
    • <table id="ae6ms"></table><table id="ae6ms"><td id="ae6ms"></td></table>
    • <td id="ae6ms"></td>
    • <table id="ae6ms"><li id="ae6ms"></li></table>
    • <table id="ae6ms"></table>