从网上看到了各种反射与表达式树的性能对比.于是自己也写了代码进行测试.发现循环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倍有很大的区别)