------------------
前言
------------------
反射性能实在是太恶劣,在通讯系统、数据库系统中已经无法忍受了。于是我在codeproject上找到一篇使用DynamicMethod的替代方法。http://www.codeproject.com/KB/cs/Dynamic_Code_Generation.aspx
可是作者实在也太简陋了,目前仅支持FIeld / Property,于是我扩展了。
1.支持FIeld / 带参数Constructor / Property / Index
2.操作过程和反射过程一摸一样。
------------------
代码测试结果
------------------
测试对象:
代码
class
SomeClass
{
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 动态编译
代码
//
set field
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
"
);
}
测试结果:
代码
------
Test started: Assembly: Pixysoft.Framework.Reflection.dll
------
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动态编译
代码
public
void
test004()
{
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
"
);
}
测试结果
代码
------
Test started: Assembly: Pixysoft.Framework.Reflection.dll
------
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动态编译
代码
public
void
test006()
{
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
"
);
}
测试结果
代码
------
Test started: Assembly: Pixysoft.Framework.Reflection.dll
------
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动态编译
代码
public
void
test005()
{
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
"
);
}
测试结果
代码
------
Test started: Assembly: Pixysoft.Framework.Reflection.dll
------
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动态编译
代码
public
void
test008()
{
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
"
);
}
测试结果
代码
------
Test started: Assembly: Pixysoft.Framework.Reflection.dll
------
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动态编译
代码
public
void
test007()
{
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
"
);
}
测试结果
代码
------
Test started: Assembly: Pixysoft.Framework.Reflection.dll
------
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去托管了。