反射 表达式树 DLR 性能,效率 对比

从网上看到了各种反射与表达式树的性能对比.于是自己也写了代码进行测试.发现循环10万次以下时性能相差不大.





<%@ Page Language="C#" AutoEventWireup="true" CodeFile="反射表达式树DLR性能对比.aspx.cs" Inherits="序列反射動態程式集_反射表达式树DLR性能对比" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>反射表达式树DLR性能对比</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    </div>
    </form>
</body>
</html>







using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class 序列反射動態程式集_反射表达式树DLR性能对比 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {


        //填充数据
        Action act = () => { InitTypePropertyAssignExpression<TestCalass>(true); };


        Response.Write("转换完成:" + act.StopwatchRun() + "毫秒<br/>");


        List<double> lis = new List<double>() { 0.1,0.5, 10, 20, 30, 50,100,200 };

        //不同循环次数对比
        foreach (double num in lis)
        {

            RunDiff(num);
        }

    }


    #region 填充与计算方法

    Random dom = new Random();
    /// <summary>
    /// 开始比较方法
    /// </summary>
    /// <param name="num">进行多少次比较</param>
    public void RunDiff(double num = 10)
    {
        //10万次计算时间对比
        var arr = System.Linq.Enumerable.Range(1, (int)(num * 10000)).ToList();

        TestCalass c = new TestCalass();

        Action 手动编码 = () =>
        {
            arr.ForEach((o) =>
            {
                
                产生随机值并且填充对像(c, 2);
            });
        };

        Action 表达式树 = () =>
        {
            arr.ForEach((o) =>
            {
                //TestCalass c = new TestCalass();
                产生随机值并且填充对像(c, 0);

            });
        };


        Action 反射 = () =>
        {
            arr.ForEach((o) =>
            {
               // TestCalass c = new TestCalass();
                产生随机值并且填充对像(c, 1);
            });
        };

        long v0, v1, v2;

        Response.Write(string.Format("{0} 运行 {1} 万次,用时{2}毫秒<br/>", "手动编码", arr.Count / 10000.0, v2 = 手动编码.StopwatchRun()));
        Response.Write(string.Format("{0} 运行 {1} 万次,用时{2}毫秒<br/>", "表达式树", arr.Count / 10000.0, v0 = 表达式树.StopwatchRun()));
        Response.Write(string.Format("{0} 运行 {1} 万次,用时{2}毫秒<br/>", "反射赋值", arr.Count / 10000.0, v1 = 反射.StopwatchRun()));
        Response.Write(string.Format("{0}为基准值 {1}用时{2};   {3}用时{4}  相差:{5},快了{6}倍 ", v2, "表达式树", v0-v2, "反射赋值", v1-v2, (v1 - v0),( v1-v0 )/(v0-v2) ));
        Response.Write(string.Format("--------------------------<br/>"));

    }

    /// <summary>
    /// 设置反射数据
    /// </summary>
    public void RefSetvalue(System.Reflection.PropertyInfo p, TestCalass t, object val)
    {
        p.SetValue(t, val, null);
    }

    public void 产生随机值并且填充对像(TestCalass c, int isExpression = 1)
    {
        foreach (var p in exProinfoDic)
        {

            if (p.Value.PropertyType == typeof(int))
            {
                int val = dom.Next(1, int.MaxValue);
                //是否使用表达式赋值
                if (isExpression == 0)
                {
                    //传值
                    p.Value.ActionAssign(val, c);
                    continue;
                }
                if (isExpression == 1)
                {
                    RefSetvalue(p.Value.PropertyInfo, c, val);
                    continue;
                }
                if (isExpression == 2)
                {
                    c.a = val;
                    continue;
                }
            }


            if (p.Value.PropertyType == typeof(string))
            {
                string val = Guid.NewGuid().ToString();
                //是否使用表达式赋值
                if (isExpression == 0)
                {
                    //传值
                    p.Value.ActionAssign(val, c);
                    continue;
                }
                if (isExpression == 1)
                {
                    RefSetvalue(p.Value.PropertyInfo, c, val);
                    continue;
                }
                if (isExpression == 2)
                {
                    c.b = val;
                    continue;
                }
            }

            if (p.Value.PropertyType == typeof(DateTime))
            {
                int vald = dom.Next(1, int.MaxValue);
                DateTime val = DateTime.Now.AddMilliseconds(vald);
                //是否使用表达式赋值
                if (isExpression == 0)
                {
                    //传值
                    p.Value.ActionAssign(val, c);
                    continue;
                }
                if (isExpression == 1)
                {
                    RefSetvalue(p.Value.PropertyInfo, c, val);
                    continue;
                }
                if (isExpression == 2)
                {
                    c.c = val;
                    continue;
                }
            }

            if (p.Value.PropertyType == typeof(double[]))
            {
                double[] val = new double[50];
                for (int i = 0; i < val.Length; i++)
                {
                    val[i] = dom.Next(1, int.MaxValue);
                }
                //是否使用表达式赋值
                if (isExpression == 0)
                {
                    //传值
                    p.Value.ActionAssign(val, c);
                    continue;
                }
                if (isExpression == 1)
                {
                    RefSetvalue(p.Value.PropertyInfo, c, val);
                    continue;
                }
                if (isExpression == 2)
                {
                    c.Arr = val;
                    continue;
                }
            }

        }
    }

    #endregion



    /// <summary>
    /// 初始化类型属性表达式操作,只能处理基元类型
    /// </summary>
    ///<exception cref="System.Collections.Generic.KeyNotFoundException">没有找到合适的处理方法</exception>
    ///<param name="NotFindConvertObject">没有找到合适类型自动转换成为object</param>
    public void InitTypePropertyAssignExpression<T>(bool NotFindConvertObject = false)
    {
        //初始化表达式
        foreach (var p in typeof(T).GetProperties())
        {
            //C# 所有基元类型
            if (CreateExpression<T, byte>(p)) { continue; }
            if (CreateExpression<T, sbyte>(p)) { continue; }
            if (CreateExpression<T, int>(p)) { continue; }
            if (CreateExpression<T, uint>(p)) { continue; }
            if (CreateExpression<T, short>(p)) { continue; }
            if (CreateExpression<T, ushort>(p)) { continue; }
            if (CreateExpression<T, long>(p)) { continue; }
            if (CreateExpression<T, ulong>(p)) { continue; }
            if (CreateExpression<T, float>(p)) { continue; }
            if (CreateExpression<T, double>(p)) { continue; }
            if (CreateExpression<T, char>(p)) { continue; }
            if (CreateExpression<T, bool>(p)) { continue; }
            if (CreateExpression<T, string>(p)) { continue; }
            if (CreateExpression<T, decimal>(p)) { continue; }
            if (CreateExpression<T, object>(p)) { continue; }
            if (CreateExpression<T, DateTime>(p)) { continue; }

            if (NotFindConvertObject)
            {
                //没有找到合适的类型自动转换成为object
                CreateExpression<T, object>(p, true);
            }
            else
            {
                throw new KeyNotFoundException("没有找到合适的基元类型");

            }
        }
    }

    /// <summary>
    /// 创建属性表达式数据实体
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <typeparam name="TValue">属性的 值类型</typeparam>
    /// <param name="p">属性信息</param>
    /// <param name="toObject">转换成为Object</param>
    /// <returns>成功返回true</returns>
    protected bool CreateExpression<T, TValue>(System.Reflection.PropertyInfo p, bool toObject = false)
    {

        if (p.PropertyType == typeof(TValue) || toObject)
        {
            //添加到缓存集合
            return exProinfoDic.TryAdd(p.Name, new ExpressionPropertyInfo()
             {
                 PropertyType = p.PropertyType,
                 PropertyName = p.Name,
                 PropertyInfo = p,
                 ActionAssign = GetExpression<T, TValue>(p.Name)
             });
        }



        return false;
    }

    /// <summary>
    /// 表达式类型属性信息对像缓存
    /// </summary>
    System.Collections.Concurrent.ConcurrentDictionary<string, ExpressionPropertyInfo> exProinfoDic = new System.Collections.Concurrent.ConcurrentDictionary<string, ExpressionPropertyInfo>();


    /// <summary>
    /// 一个属性传值操作 表达式
    /// </summary>
    /// <param name="propertyName">属性名</param>
    /// <typeparam name="T">实体类型值</typeparam>
    /// <typeparam name="TValue">属性类型值</typeparam>
    /// <returns></returns>
    public Func<TValue, T, TValue> GetExpression<T, TValue>(string propertyName)
    {
        Type t = typeof(T);
        System.Reflection.PropertyInfo pro = t.GetProperty(propertyName);
        return GetExpression<T, TValue>(pro);
    }

    /// <summary>
    /// 一个属性传值操作 表达式
    /// </summary>
    /// <param name="propertyInfo">属性对像</param>
    /// <typeparam name="T">实体类型值</typeparam>
    /// <typeparam name="TValue">属性类型值</typeparam>
    /// <returns></returns>
    public Func<TValue, T, TValue> GetExpression<T, TValue>(System.Reflection.PropertyInfo propertyInfo)
    {
        Type t = typeof(T);
        Type vt = typeof(TValue);
        //参数p
        System.Linq.Expressions.ParameterExpression p = System.Linq.Expressions.Expression.Parameter(t, "p");
        //参数值 v
        System.Linq.Expressions.ParameterExpression v = System.Linq.Expressions.Expression.Parameter(vt, "v");

        //属性 curp
        System.Linq.Expressions.MemberExpression curP = System.Linq.Expressions.Expression.Property(p, propertyInfo);


        //赋值操作
        System.Linq.Expressions.BinaryExpression ass = null;
        if (vt != propertyInfo.PropertyType)
        {
            //转换表达式 v
            System.Linq.Expressions.UnaryExpression conv = System.Linq.Expressions.Expression.Convert(v, propertyInfo.PropertyType);
            //赋值操作
            ass = System.Linq.Expressions.Expression.Assign(curP, conv);

        }
        else
        {
            ass = System.Linq.Expressions.Expression.Assign(curP, v);
        }


        //表达式结果
        System.Linq.Expressions.Expression<Func<TValue, T, TValue>> result = System.Linq.Expressions.Expression.Lambda<Func<TValue, T, TValue>>(ass, v, p);

        //返回编译后结果
        return result.Compile();

    }



    /// <summary>
    /// 表达式类型属性信息对像
    /// </summary>
    public class ExpressionPropertyInfo
    {
        /// <summary>
        /// 属性名
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 属性类型
        /// </summary>
        public Type PropertyType { get; set; }

        /// <summary>
        /// 属性对像
        /// </summary>
        public System.Reflection.PropertyInfo PropertyInfo { get; set; }

        /// <summary>
        /// 赋值操作委托
        /// </summary>
        public dynamic ActionAssign { get; set; }

    }

    /// <summary>
    /// 测试用类
    /// </summary>
    public class TestCalass
    {
        public int a { get; set; }

        public string b { get; set; }

        public DateTime c { get; set; }

        public double[] Arr { get; set; }

    }
}


扩展方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace System
{
    /// <summary>
    /// 通用调试方法
    /// </summary>
    public static class TongTestExpand
    {

        /// <summary>
        /// 测试此方法运行时间
        /// </summary>
        /// <param name="act">运行方法</param>
        /// <returns>返回时间单位毫秒</returns>
        public static long StopwatchRun(this Action act)
        {
            System.Diagnostics.Stopwatch sa = new System.Diagnostics.Stopwatch();
            long result = 0;
            sa.Restart();

            try
            {
                act();
            }
            finally
            {

                sa.Stop();
                result = sa.ElapsedMilliseconds;
            }
            return result;
        }

    }
}


运行结果1(不需要每次创建值)

转换完成:11毫秒
手动编码 运行 0.1 万次,用时7毫秒
表达式树 运行 0.1 万次,用时48毫秒
反射赋值 运行 0.1 万次,用时6毫秒
7为基准值 表达式树用时41; 反射赋值用时-1 相差:-42,快了-1倍 
--------------------------
手动编码 运行 0.5 万次,用时18毫秒
表达式树 运行 0.5 万次,用时22毫秒
反射赋值 运行 0.5 万次,用时33毫秒
18为基准值 表达式树用时4; 反射赋值用时15 相差:11,快了2倍 
--------------------------
手动编码 运行 10 万次,用时403毫秒
表达式树 运行 10 万次,用时445毫秒
反射赋值 运行 10 万次,用时667毫秒
403为基准值 表达式树用时42; 反射赋值用时264 相差:222,快了5倍 
--------------------------
手动编码 运行 20 万次,用时784毫秒
表达式树 运行 20 万次,用时901毫秒
反射赋值 运行 20 万次,用时1348毫秒
784为基准值 表达式树用时117; 反射赋值用时564 相差:447,快了3倍 
--------------------------
手动编码 运行 30 万次,用时1178毫秒
表达式树 运行 30 万次,用时1344毫秒
反射赋值 运行 30 万次,用时2003毫秒
1178为基准值 表达式树用时166; 反射赋值用时825 相差:659,快了3倍 
--------------------------
手动编码 运行 50 万次,用时1987毫秒
表达式树 运行 50 万次,用时2285毫秒
反射赋值 运行 50 万次,用时3396毫秒
1987为基准值 表达式树用时298; 反射赋值用时1409 相差:1111,快了3倍 
--------------------------
手动编码 运行 100 万次,用时4013毫秒
表达式树 运行 100 万次,用时4625毫秒
反射赋值 运行 100 万次,用时6798毫秒
4013为基准值 表达式树用时612; 反射赋值用时2785 相差:2173,快了3倍 
--------------------------
手动编码 运行 200 万次,用时8277毫秒
表达式树 运行 200 万次,用时9281毫秒
反射赋值 运行 200 万次,用时13773毫秒
8277为基准值 表达式树用时1004; 反射赋值用时5496 相差:4492,快了4倍 
--------------------------



运行效果2(在方法中每次创建值)

转换完成:11毫秒
手动编码 运行 0.1 万次,用时7毫秒
表达式树 运行 0.1 万次,用时48毫秒
反射赋值 运行 0.1 万次,用时6毫秒
7为基准值 表达式树用时41; 反射赋值用时-1 相差:-42,快了-1倍 
--------------------------
手动编码 运行 0.5 万次,用时18毫秒
表达式树 运行 0.5 万次,用时22毫秒
反射赋值 运行 0.5 万次,用时33毫秒
18为基准值 表达式树用时4; 反射赋值用时15 相差:11,快了2倍 
--------------------------
手动编码 运行 10 万次,用时403毫秒
表达式树 运行 10 万次,用时445毫秒
反射赋值 运行 10 万次,用时667毫秒
403为基准值 表达式树用时42; 反射赋值用时264 相差:222,快了5倍 
--------------------------
手动编码 运行 20 万次,用时784毫秒
表达式树 运行 20 万次,用时901毫秒
反射赋值 运行 20 万次,用时1348毫秒
784为基准值 表达式树用时117; 反射赋值用时564 相差:447,快了3倍 
--------------------------
手动编码 运行 30 万次,用时1178毫秒
表达式树 运行 30 万次,用时1344毫秒
反射赋值 运行 30 万次,用时2003毫秒
1178为基准值 表达式树用时166; 反射赋值用时825 相差:659,快了3倍 
--------------------------
手动编码 运行 50 万次,用时1987毫秒
表达式树 运行 50 万次,用时2285毫秒
反射赋值 运行 50 万次,用时3396毫秒
1987为基准值 表达式树用时298; 反射赋值用时1409 相差:1111,快了3倍 
--------------------------
手动编码 运行 100 万次,用时4013毫秒
表达式树 运行 100 万次,用时4625毫秒
反射赋值 运行 100 万次,用时6798毫秒
4013为基准值 表达式树用时612; 反射赋值用时2785 相差:2173,快了3倍 
--------------------------
手动编码 运行 200 万次,用时8277毫秒
表达式树 运行 200 万次,用时9281毫秒
反射赋值 运行 200 万次,用时13773毫秒
8277为基准值 表达式树用时1004; 反射赋值用时5496 相差:4492,快了4倍 
--------------------------


和网上(所说的100倍有很大的区别)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值