[ZT]使用DynamicMethod替代反射,提高100倍的性能!(附源码)
原文转自:http://www.cnblogs.com/zc22/archive/2010/06/01/1749459.html
------------------
前言
------------------
反射性能实在是太恶劣,在通讯系统、数据库系统中已经无法忍受了。于是我在codeproject上找到一篇使用DynamicMethod的替代方法。http://www.codeproject.com/KB/cs/Dynamic_Code_Generation.aspx
可是作者实在也太简陋了,目前仅支持FIeld / Property,于是我扩展了。
1.支持FIeld / 带参数Constructor / Property / Index
2.操作过程和反射过程一摸一样。
------------------
代码测试结果
------------------
测试对象:
{
public int name;
public string sname;
public SomeClass()
{
}
public SomeClass(string name)
{
this.sname = name;
}
public int Name
{
get { return name; }
set { name = value; }
}
public string Sname
{
get { return sname; }
set { sname = value; }
}
public string this[int index, string name, int a, int b, string c, double d]
{
get
{
return index.ToString() + name;
}
set
{
}
}
}
SetFIeld的反射 VS 动态编译
public void test003()
{
SomeClass c = new SomeClass();
FieldInfo field = c.GetType().GetFields()[1];
StartTest("begin reflection.");
for (int i = 0; i < 10000000; i++)
{
field.SetValue(c, "test");
}
EndTest("end reflection");
IDynamicFieldInfo dfield = new DynamicType(c.GetType()).GetFields()[1];
StartTest("begin dynamic.");
for (int i = 0; i < 10000000; i++)
{
dfield.SetValue(c, "test");
}
EndTest("end dynamic");
}
测试结果:
begin reflection.
end reflection
00:00:28.3593750
begin dynamic.
end dynamic
00:00:00.2500000
1 passed, 0 failed, 0 skipped, took 28.70 seconds (Ad hoc).
性能提高100多倍。
GetFIeld 反射VS动态编译
{
SomeClass c = new SomeClass();
FieldInfo field = c.GetType().GetFields()[1];
StartTest("begin reflection.");
field.SetValue(c, "test");
for (int i = 0; i < 10000000; i++)
{
field.GetValue(c);
}
EndTest("end reflection");
IDynamicFieldInfo dfield = new DynamicType(c.GetType()).GetFields()[1];
dfield.SetValue(c, "test");
StartTest("begin dynamic.");
for (int i = 0; i < 10000000; i++)
{
dfield.GetValue(c);
}
EndTest("end dynamic");
}
测试结果
begin reflection.
end reflection
00:00:18.9531250
begin dynamic.
end dynamic
00:00:00.2031250
1 passed, 0 failed, 0 skipped, took 19.25 seconds (Ad hoc).
提高接近100倍
GetProperty 反射VS动态编译
{
SomeClass c = new SomeClass();
PropertyInfo property = c.GetType().GetProperties()[1];
StartTest("begin reflection.");
for (int i = 0; i < 1000000; i++)
{
property.GetValue(c, null);
}
EndTest("end reflection");
IDynamicPropertyInfo dproperty = new DynamicType(c.GetType()).GetProperties()[1];
StartTest("begin dynamic.");
for (int i = 0; i < 1000000; i++)
{
dproperty.GetValue(c, null);
}
EndTest("end dynamic");
}
测试结果
begin reflection.
end reflection
00:00:05.5312500
begin dynamic.
end dynamic
00:00:00.0468750
1 passed, 0 failed, 0 skipped, took 5.66 seconds (Ad hoc).
依然100倍!!!
SetProperty 反射VS动态编译
{
SomeClass c = new SomeClass();
PropertyInfo property = c.GetType().GetProperties()[0];
StartTest("begin reflection.");
for (int i = 0; i < 1000000; i++)
{
property.SetValue(c, i, null);
}
EndTest("end reflection");
IDynamicPropertyInfo dproperty = new DynamicType(c.GetType()).GetProperties()[0];
StartTest("begin dynamic.");
for (int i = 0; i < 1000000; i++)
{
dproperty.SetValue(c, i, null);
}
EndTest("end dynamic");
}
测试结果
begin reflection.
end reflection
00:00:09.0625000
begin dynamic.
end dynamic
00:00:00.0468750
1 passed, 0 failed, 0 skipped, took 9.20 seconds (Ad hoc).
遥遥领先250倍
Constructor 反射VS动态编译
{
Type type = typeof(SomeClass);
StartTest("begin reflection.");
for (int i = 0; i < 1000000; i++)
{
object result = Activator.CreateInstance(type, "hello");
}
EndTest("end reflection");
StartTest("begin dynamic.");
IDynamicConstructorInfo dConstructorInfo = new DynamicType(type).GetConstructors()[1];
for (int i = 0; i < 1000000; i++)
{
object result = dConstructorInfo.Invoke(new object[] { "hello" });
}
EndTest("end dynamic");
StartTest("begin dynamic.");
for (int i = 0; i < 1000000; i++)
{
object result = new DynamicType(type).GetConstructors()[1].Invoke(new object[] { "hello" });
}
EndTest("end dynamic");
}
测试结果
begin reflection.
end reflection
00:00:07.5937500
begin dynamic.
end dynamic
00:00:00.1250000
begin dynamic.
end dynamic
00:00:01.2187500
1 passed, 0 failed, 0 skipped, took 9.02 seconds (Ad hoc).
60倍左右。
GetIndex 反射VS动态编译
{
SomeClass c = new SomeClass();
Type type = c.GetType();
PropertyInfo property = type.GetProperties()[2];
StartTest("begin reflection.");
for (int i = 0; i < 1000000; i++)
{
property.SetValue(c, i.ToString(), new object[] { 0, "", 0, 0, "", 0 });
}
EndTest("end reflection");
IDynamicPropertyInfo dproperty = new DynamicType(type).GetProperties()[2];
StartTest("begin dynamic.");
for (int i = 0; i < 1000000; i++)
{
dproperty.SetValue(c, i.ToString(), new object[] { 0, "", 0, 0, "", (double)0 });
}
EndTest("end dynamic");
StartTest("begin dynamic set property.");
for (int i = 0; i < 1000000; i++)
{
new DynamicType(type).GetProperties()[2].SetValue(c, i.ToString(), new object[] { 0, "", 0, 0, "", (double)0 });
}
EndTest("end dynamic");
}
测试结果
begin reflection.
end reflection
00:00:07.2656250
begin dynamic.
end dynamic
00:00:00.5000000
begin dynamic set property.
end dynamic
00:00:01.7968750
1 passed, 0 failed, 0 skipped, took 9.64 seconds (Ad hoc).
30倍左右(性能损失在了装箱拆箱)
----------------------
源码下载与备注
----------------------
http://www.boxcn.net/shared/8qqgob51hi
空间由boxcn.net提供,放心下载。
开始的时候,想到老赵的反射开源,可是他用Linq去实现,在dotnet 2.0不支持,而现状是大部分服务器应用还是dotnet 2.0, 只好放弃。
之后codeproject找到了篇文章介绍了DynamicMethod,可是作者写的比较龊,于是我稍微扩展了,直接参考Type的模型设计,得到了DynamicType,然后接下来的操作也TYpe一样。
目前MethodInfo无法使用DynamicMethod替代,因为存在了范型,无法使用通用的delegate去模拟。。。
本来以为,通过DynamicMethod,最少能提高性能10倍吧,可是用在了项目上,却发现没有变化!!!!
我在序列化中使用,却发现性能根本没有太大的提升,后来发现反射去Get/Set实际占性能损失很小,另外一大部分在
1. 集合的操作(List / Dictionary / ...)
2. Type.GetProperties 等类似的操作。
3. attribute的获取操作。
没办法,看来要继续努力,接下来打算把整个Type对象使用Dynamic去托管了。