.netでの反射、emit、expression、dynamicのパフォーマンス比較
13356 ワード
class
Student
{
public
string
Name {
get
;
set
; }
}
static
double
Test(
int
loop, Student stu, Func
<
Student,
string
>
action)
{
var watch
=
Stopwatch.StartNew();
string
s
=
null
;
for
(var i
=
0
; i
<
loop; i
++
)
s
=
action(stu);
return
watch.ElapsedTicks;
}
static
Func
<
Student,
string
>
NativeGetter()
{
return
s
=>
s.Name;
}
static
Func
<
Student,
string
>
ReflectedGetter()
{
var type
=
typeof
(Student);
var prop
=
type.GetProperty(
"
Name
"
);
return
s
=>
(
string
)prop.GetValue(s,
null
);
}
static
Func
<
Student,
string
>
EmittedGetter()
{
var dm
=
new
DynamicMethod(name:
"
EmittedGetter
"
, returnType:
typeof
(
string
), parameterTypes:
new
[] {
typeof
(Student) }, owner:
typeof
(Student));
var type
=
typeof
(Student);
var prop
=
type.GetMethod(
"
get_Name
"
);
var il
=
dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, prop);
il.Emit(OpCodes.Ret);
return
(Func
<
Student,
string
>
)dm.CreateDelegate(
typeof
(Func
<
Student,
string
>
));
}
static
Func
<
Student,
string
>
ExpressionGetter()
{
var type
=
typeof
(Student);
var prop
=
type.GetMethod(
"
get_Name
"
);
ParameterExpression pa
=
Expression.Parameter(
typeof
(Student));
Expression body
=
Expression.Call(pa, prop);
return
Expression.Lambda
<
Func
<
Student,
string
>>
(body, pa).Compile();
}
static
Func
<
Student,
string
>
DynamicGetter()
{
return
s
=>
{ dynamic d
=
s;
return
d.Name; };
}
[MethodImpl(MethodImplOptions.NoOptimization)]
public
static
void
Run()
{
const
int
loop
=
5000000
;
var stu
=
new
Student {Name
=
"
Mike
"
};
var dynamic
=
Test(loop, stu, DynamicGetter());
var expression
=
Test(loop, stu, ExpressionGetter());
var native
=
Test(loop, stu, NativeGetter());
var emitted
=
Test(loop, stu, EmittedGetter());
var reflected
=
Test(loop, stu, ReflectedGetter());
Console.WriteLine(
"
native:{0}
dynamic:{1}
emit:{2}
expression:{3}
reflection:{4}
"
,
1
, dynamic
/
native, emitted
/
native, expression
/
native, reflected
/
native);
Console.ReadKey();
}
テスト結果
1.サイクル数が比較的小さい場合、loop=1000
native:1dynamic:540.444964871194emit:0.704918032786885expression:0.224824355971897reflection:8.37002341920375
2. loop=5000000
native:1dynamic:4.37328053807767emit:0.96159470600998expression:1.00412887828162reflection:35.909097418095