從網上看到了各種反射與表達式樹的性能對比.於是自己也寫了代碼進行測試.發現循環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倍有很大的區別)