使用DynamicMethod替代反射,提高100倍的性能!(附源码)

------------------

前言

------------------ 

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

原文地址:https://www.cnblogs.com/zc22/p/1749459.html