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

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件下載最安全的下載網(wǎng)站、值得信賴的軟件下載站!

      首頁編程開發(fā)C#.NET → .Net4.0用表達式樹構(gòu)建委托改善反射性能

      .Net4.0用表達式樹構(gòu)建委托改善反射性能

      相關(guān)軟件相關(guān)文章發(fā)表評論 來源:西西整理時間:2013/2/4 8:39:15字體大小:A-A+

      作者:張偉文點擊:0次評論:0次標簽: 反射

      • 類型:免DVD補丁大小:2.7M語言:中文 評分:5.0
      • 標簽:
      立即下載

      最近搞一個系統(tǒng)時由于在比較關(guān)鍵地方用到反射了,所以要關(guān)注了一下反射的性能問題。

      .Net4.0反射性能改善

      看老趙的文章,老趙得到的結(jié)果是這樣的:

      00:00:00.0125539 (Directly invoke)
      00:00:04.5349626 (Reflection invoke)
      00:00:00.0322555 (Dynamic executor)

      而我把代碼搞下來自己運行得到這樣的結(jié)果:

      00:00:00.0009710 (Directly invoke)
      00:00:00.4142893 (Reflection invoke)
      00:00:00.0194501 (Dynamic executor)

      這里不是說機器性能造成絕對的時間,而是差距比例完全不一樣,想了一陣想起了老趙當時應(yīng)該是基于.Net3.5,果斷把程序的目標框架切換到.Net3.5,結(jié)果如下:

      00:00:00.0018801 (Directly invoke)
      00:00:02.4288876 (Reflection invoke)
      00:00:00.0141537 (Dynamic executor)
      三者的差距仍然有些不一樣,老趙那邊的直接調(diào)用與動態(tài)執(zhí)行同一數(shù)量級的結(jié)果還是沒有。但發(fā)現(xiàn)了另一些信息。反射和直接調(diào)用方法.Net4.0比.Net3.5有非常大的改善,特別是反射,性能提升了好幾倍。反而構(gòu)建表達式樹動態(tài)調(diào)用的方式性能比.Net3.5差了一點。但是相對反射還是有差距,按照這個比例,寫寫表達式樹還是值得的。

      改善老趙的DynamicMethodExecutor

      老趙的那篇的文章的思路是使用DynamicMethodExecutor來構(gòu)造一個萬能的委托Func<object, object[], object>其中第一個參數(shù)是實例對象,第二是參數(shù)列表,第三是返回值。.Net4.0的表達式樹要比3.5的先進一點,經(jīng)過一番改造發(fā)現(xiàn)是不需要這么一個萬能委托的,直接用Expression.Lambda.Compile()編譯出來的Delegate強制轉(zhuǎn)換為強類型的委托來得更加簡單。全部代碼一個方法即可,精簡了許多。

      /// <summary>
      /// 動態(tài)構(gòu)造委托
      /// </summary>
      /// <param name="methodinfo">方法元數(shù)據(jù)</param>
      /// <returns>委托</returns>
      public static Delegate BuildDynamicDelegate(MethodInfo methodInfo)
      {
          if (methodInfo == null)
              throw new ArgumentNullException("methodInfo");
      
          var paramExpressions = methodInfo.GetParameters().Select((p, i) =>
          {
              var name = "param" + (i + 1).ToString(CultureInfo.InvariantCulture);
              return Expression.Parameter(p.ParameterType, name);
          }).ToList();
      
          MethodCallExpression callExpression;
          if (methodInfo.IsStatic)
          {
              //Call(params....)
              callExpression = Expression.Call(methodInfo, paramExpressions);
          }
          else
          {
              var instanceExpression = Expression.Parameter(methodInfo.ReflectedType, "instance");
              //insatnce.Call(params….)
              callExpression = Expression.Call(instanceExpression, methodInfo, paramExpressions);
              paramExpressions.Insert(0, instanceExpression);
          }
          var lambdaExpression = Expression.Lambda(callExpression, paramExpressions);
          return lambdaExpression.Compile();
      }

      使用時轉(zhuǎn)換為強類型的委托即可:

      var action = (Action<TInstance, T1, T2>)BuildDynamicDelegate(methodInfo);
      var func = (Func<TInstance, T1, T2, TReturn>)BuildDynamicDelegate(methodInfo);

      老趙那個委托都是object,使用時的類型轉(zhuǎn)換,還有裝箱,拆箱都會有一定的性能損失,而強類型就沒有這個問題。

      首先在老趙的那篇文章上一個方法改為兩個方法,然后測試:

      public void Call1(object o1, object o2, object o3) { }
      public void Call2(int o1, int o2, int o3) { }
      private static void DynamicExecutor_ObjectType()
      {
          var executor = new DynamicMethodExecutor(Call1MethodInfo);
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i < Times; i++)
          {
              executor.Execute(ProgramInstance, ObjectParameters);
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Dynamic executor(object))(JeffreyZhao)");
      }
      private static void DynamicExecutor_IntType()
      {
          var executor = new DynamicMethodExecutor(Call2MethodInfo);
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i < Times; i++)
          {
              executor.Execute(ProgramInstance, IntParameters);
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Dynamic executor(int))(JeffreyZhao)");
      }
      private static void DynamicExecutor_StrongObject()
      {
          var action = DynamicMethodBuilder.BuildAction<Program, object, object, object>(Call1MethodInfo);
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i < Times; i++)
          {
              action(ProgramInstance, ObjectParameters[0], ObjectParameters[1], ObjectParameters[2]);
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Dynamic executor(object))(zhangweiwen)");
      }
      
      private static void DynamicExecutor_StrongInt()
      {
          var action = DynamicMethodBuilder.BuildAction<Program, int, int, int>(Call2MethodInfo);
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i < Times; i++)
          {
              action(ProgramInstance, IntParameters1[0], IntParameters1[1], IntParameters1[2]);
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Dynamic executor(int))(zhangweiwen)");
      }

      結(jié)果:

      00:00:00.0188422 (Dynamic executor(object))(JeffreyZhao)
      00:00:00.0210869 (Dynamic executor(int))(JeffreyZhao)
      00:00:00.0142841 (Dynamic executor(object))(zhangweiwen)
      00:00:00.0147589 (Dynamic executor(int))(zhangweiwen)

      差距不大,但是還是有一定得改善,特別參數(shù)是int的方法,用了強類型后性能比較穩(wěn)定,不會出現(xiàn)偏差。

      構(gòu)建委托動態(tài)賦值

      既然有動態(tài)調(diào)用方法,同樣也可以動態(tài)賦值,而且據(jù)我的經(jīng)驗,根據(jù)PropertyInfo的SetValue去反射設(shè)屬性值用得比反射調(diào)用方法更加頻繁。所以同樣需要有方法來動態(tài)構(gòu)建委托改善性能。

      幸好,.Net4.0提供了支持,.Net4.0新增了Expression.Assign來表示一個賦值表達式。有了它,構(gòu)建起來比方法的更加簡單:

      private static Action<TInstance, TProperty> BuildSetPropertyAction<TInstance, TProperty>(PropertyInfo propertyInfo)
      {
          var instanceParam = Expression.Parameter(typeof(TInstance), "instance");
          var valueParam = Expression.Parameter(typeof(TProperty), "value");
          //instance.Property
          var propertyProperty = Expression.Property(instanceParam, propertyInfo);
          //instance.Property = value
          var assignExpression = Expression.Assign(propertyProperty, valueParam);
          var lambdaExpression = Expression.Lambda<Action<TInstance, TProperty>>(assignExpression, instanceParam, valueParam);
          return lambdaExpression.Compile();
      }

      直接返回了強類型的委托,所以使用起來更加簡單:

      var action = BuildSetPropertyAction<Program, object>(ObjectPropertyInfo);
      action(ProgramInstance, ObjectValue);

      來測試一下性能:

      private static void DirectlySetValueType()
      {
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i &lt; Times; i++)
          {
              ProgramInstance.IntProperty = IntValue;
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Directly Set IntProperty)");
      }
      
      private static void ReflectionSetValueType()
      {
          var watch2 = new Stopwatch();
          watch2.Start();
          for (var i = 0; i &lt; Times; i++)
          {
              IntPropertyInfo.SetValue(ProgramInstance, IntValue, null);
          }
          watch2.Stop();
          Console.WriteLine(watch2.Elapsed + " (Reflection Set IntProperty)");
      }
      
      private static void DynamicSetValueType()
      {
          var action = BuildSetPropertyAction&lt;Program, int&gt;(IntPropertyInfo);
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i &lt; Times; i++)
          {
              action(ProgramInstance, IntValue);
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Dynamic Set IntProperty)");
      }
      
      private static void DirectlySetReferenceType()
      {
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i &lt; Times; i++)
          {
              ProgramInstance.ObjectProperty = ObjectValue;
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Directly Set ObjectProperty)");
      }
      
      private static void ReflectionSetReferenceType()
      {
          var watch2 = new Stopwatch();
          watch2.Start();
          for (var i = 0; i &lt; Times; i++)
          {
              ObjectPropertyInfo.SetValue(ProgramInstance, ObjectValue, null);
          }
          watch2.Stop();
          Console.WriteLine(watch2.Elapsed + " (Reflection Set ObjectProperty)");
      }
      
      private static void DynamicSetReferenceType()
      {
          var action = BuildSetPropertyAction&lt;Program, object&gt;(ObjectPropertyInfo);
          //action(ProgramInstance, ObjectValue);
          var watch1 = new Stopwatch();
          watch1.Start();
          for (var i = 0; i &lt; Times; i++)
          {
              action(ProgramInstance, ObjectValue);
          }
          watch1.Stop();
          Console.WriteLine(watch1.Elapsed + " (Dynamic Set ObjectProperty)");
      }

      結(jié)果如下:

      Test Set Value:
      00:00:00.0003237 (Directly Set IntProperty)
      00:00:00.3160570 (Reflection Set IntProperty)
      00:00:00.0132668 (Dynamic Set IntProperty)
      -----
      00:00:00.0028183 (Directly Set ObjectProperty)
      00:00:00.2937783 (Reflection Set ObjectProperty)
      00:00:00.0150118 (Dynamic Set ObjectProperty)

      雖然跟直接賦值不能比,但比反射快大概30倍。

      全部代碼,希望對大家有幫助.

        相關(guān)評論

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

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

        熱門評論

        最新評論

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

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