------------------
前言
------------------
反射性能实在是太恶劣,在通讯系统、数据库系统中已经无法忍受了。于是我在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去托管了。