日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

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

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

      相關(guān)軟件相關(guān)文章發(fā)表評論 來源:tonyhuang時間:2010/2/24 14:46:05字體大。A-A+

      作者:佚名點擊:291次評論:0次標簽: 對象

      • 類型:瀏覽輔助大。2KB語言:中文 評分:7.2
      • 標簽:
      立即下載

      在這片文章中,我們暫時放一放Activator.CreateInstance(Type)和Activator.CreateInstance<T>()之間的性能差異,去探索一下,為什么使用泛型約束的速度和CreateInstance<T>()差不多(用屁股都能猜到應(yīng)該是直接調(diào)用了CreateInstance<T>())。

       


      首先我們寫一個小程序來驗證我們的猜想:

      1 using System;
      2
      3 namespace GenericNew
      4 {
      5 public class Program
      6 {
      7 public static void Main(string[] args)
      8 {
      9 CreateInstance<Program>();
      10 new Program();
      11 }
      12
      13 public static T CreateInstance<T>() where T: new()
      14 {
      15 return new T();
      16 }
      17 }
      18 }
       

      編譯了以后用reflector來查看編譯的結(jié)果:

      1 public static T CreateInstance<T>() where T: new()
      2 {
      3 return new T();
      4 }
      5
       

      看起來沒有什么問題啊,跟寫的時候一樣美妙,也沒有見到System.Activator.CreateInstance<T>()的蹤影。

      那么,讓我們切換到msil模式看看:

      1 .method public hidebysig static !!T CreateInstance<.ctor T>() cil managed
      2 {
      3 .maxstack 2
      4 .locals init (
      5 [0] !!T local,
      6 [1] !!T local2)
      7 L_0000: nop
      8 L_0001: ldloca.s local2
      9 L_0003: initobj !!T
      10 L_0009: ldloc.1
      11 L_000a: box !!T
      12 L_000f: brfalse.s L_001c
      13 L_0011: ldloca.s local2
      14 L_0013: initobj !!T
      15 L_0019: ldloc.1
      16 L_001a: br.s L_0021
      17 L_001c: call !!0 [mscorlib]System.Activator::CreateInstance<!!T>()
      18 L_0021: stloc.0
      19 L_0022: br.s L_0024
      20 L_0024: ldloc.0
      21 L_0025: ret
      22 }
       

      恩,發(fā)現(xiàn)[mscorlib]System.Activator::CreateInstance<!!T>()了,通過分析這段代碼,我們會發(fā)現(xiàn),其實ms對于這個的性能還是做了一定的優(yōu)化的,這段代碼:

       

      試圖采用值類型的初始化方法初始化對象,并對該對象進行裝箱操作
      裝箱失敗的情況下,調(diào)用System.Activator.CreateInstance<T>()來創(chuàng)建對象
       

      最后再返回創(chuàng)建好的對象。

      那么是不是.net本來就是通過這種方式來創(chuàng)建對象的呢?

      我們來對比一下new Program()這條語句的編譯結(jié)果:

      1 newobj instance void GenericNew.Program::.ctor()

       

      那么為什么c#編譯器沒有采用這個指令來創(chuàng)建泛型類的實例呢?

      我們需要參考一下msdn上對于newobj的用法的定義:

      http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.newobj(VS.85).aspx

      在這里,我們看到,newobj指令的使用方法是 newobj <ctor>

      也就是說,它的參數(shù)是構(gòu)造器,而非類型本身; 原因就在于,.Net允許有不同參數(shù)的構(gòu)造器存在,只有指定了構(gòu)造器,clr才知道要使用哪個構(gòu)造器來初始化對象。

      而,對于一個泛型類,在編譯器是無法知道它的泛型參數(shù)的構(gòu)造器信息的,自然就沒有辦法使用newobj指令了。

       


      這就是事實的真相,在下一篇文章中,我們將去探究,事實的終極真相。

      posted @ 2010-02-24 12:58 TonyHuang 閱讀(14) | 評論 (0) | 編輯

      .Net中各種不同的對象創(chuàng)建方式的速度差異(三)
      本文章為本人個人博客相應(yīng)文章的鏡像:

      原文地址: http://www.greatony.com/index.php/2010/02/20/speed-of-object-creation-in-dotnet-iii/

       

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

       

      使用System.Activator的非泛型方法比使用泛型方法快很多(超過200%)
      使用泛型約束和new關(guān)鍵字創(chuàng)建的速度幾乎和System.Activator的泛型方法的一樣
       

      在這篇文章里,我將會這兩個問題做一個進一步的探究,我使用的工具就是鼎鼎大名的.Net反編譯工具:Reflector,歡迎讀者跟我一起探討造成這個現(xiàn)象的原因。

      第一段 從System.Activator.CreateInstance(Type)開始

      我們先用Reflector打開.Net Framework 3.5中的mscorlib.dll,看看這里面,微軟是怎么實現(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 }
       

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

      1 public static object CreateInstance(Type type, bool nonPublic)
      2 {
      3 if (type == null)
      4 {
      5 throw new ArgumentNullException("type");
      6 }
      7 RuntimeType underlyingSystemType = type.UnderlyingSystemType as RuntimeType;
      8 if (underlyingSystemType == null)
      9 {
      10 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type");
      11 }
      12 return underlyingSystemType.CreateInstanceImpl(!nonPublic);
      13 }
      14
       

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

      1 public static object CreateInstance(Type type, bool nonPublic)
      2 {
      3 RuntimeType underlyingSystemType = type.UnderlyingSystemType as RuntimeType;
      4 return underlyingSystemType.CreateInstanceImpl(!nonPublic);
      5 }
      6
       

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

      1 internal object CreateInstanceImpl(bool publicOnly, bool skipVisibilityChecks, bool fillCache)
      2 {
      3 RuntimeTypeHandle typeHandle = this.TypeHandle;
      4 ActivatorCache cache = s_ActivatorCache;
      5 if (cache != null)
      6 {
      7 ActivatorCacheEntry entry = cache.GetEntry(this);
      8 if (entry != null)
      9 {
      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 }
      35
       

      看起來非常復(fù)雜,其實他的實現(xiàn)也也就實現(xiàn)了一個緩存機制:

       

      檢查緩存中是否存在這個構(gòu)造器的委托,如果有,就調(diào)用自己的typeHandler的Allocate()方法分配內(nèi)存,然后調(diào)用構(gòu)造器的委托初始化對象
      如果沒有緩存,就調(diào)用CreateInstanceSlow(bool isPublic, bool fillCache)創(chuàng)建對象,并填充緩存
       

      好吧繼續(xù)再看看這個CreateInstanceSlow里面干了什么事情。

      照例先貼代碼吧:

      1 private object CreateInstanceSlow(bool publicOnly, bool fillCache)
      2 {
      3 RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle;
      4 bool bNeedSecurityCheck = true;
      5 bool canBeCached = false;
      6 bool noCheck = false;
      7 this.CreateInstanceCheckThis();
      8 if (!fillCache)
      9 {
      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 }
      28
       

      這個函數(shù)寫的很復(fù)雜,其實實現(xiàn)的東西很簡單,其一是調(diào)用RuntimeTypeHandler.CreateInstance方法創(chuàng)建對象,然后再填充緩存,以加快下次創(chuàng)建對象的速度。

      好了,我們現(xiàn)在已經(jīng)非常接近事實的真相了。讓我們從另外一個角度出發(fā),看看CreateInstance<T>()干了什么事情。

      第二段 從System.Activator.CreateInstance<T>()開始

      這里,我們先看看他的實現(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 }
      8
       

      我們忽然就看到了我們熟悉的身影:RuntimeTypeHandler.CreateInstance方法,終于殊途同歸啊。。。

      也就是說,System.Activator.CreateInstance<T>()相當于調(diào)用了CreateInstanceSlow方法(但是沒有緩存機制),這應(yīng)該就是CreateInstance<T>比CreateInstance(Type)慢的主要原因,我們回顧一下這兩個方法的時間消耗:

      System.Activator.CreateInstance(Type):

       

      緩存機制時間消耗
      RuntimeTypeHandler.Allocate()內(nèi)存分配的時間消耗
      調(diào)用構(gòu)造器委托初始化數(shù)據(jù)的時間消耗
       

      這里不考慮緩存失敗,調(diào)用CreateInstanceSlow的情況,因為這個只會發(fā)生一次。

      System.Activator.CreateInstance(Type):

       

      調(diào)用RuntimeTypeHandler.CreateInstance的時間消耗
       

      在下一篇文章中,我會對這兩個函數(shù)的性能差異做進一步的分析

        相關(guān)評論

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

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

        熱門評論

        最新評論

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

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