反射(Reflection)的性能分析

记得老早以前就看到有人把反射称之为“性能杀手",正好目前正在做的erp系统为了实现扩展,系统就是架构在反射的基础之上,数据交互也都是通过反射来实现。首先系统会产生太多dll,现在刚刚起步,已经高达43个之多,由于erp系统具有很复杂的业务功能,产品在发布阶段很可能产生200甚至更多的dll,且不说这几百个项目在调试的时候,漫长的等待是多么的痛苦,在产品推出去之后,这么多的dll的版本如何维护?多现在为止,除了windows还没有见过dll超过百的系统,难道我们的系统真的比windows还要难?这些暂且不提,先测试一下反射在系统应用的性能情况,测试程序如下:

//被测试类
using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{
    
public class CTester
    
{
        
public CTester()
        
{
            a 
= 10;
        }



        
public void test1()
        
{
            a 
= (a - 0.0001* 1.0001;
        }

        
private double a;
        
public double geta() return a; }
    }

}



///测试类
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Collections;

namespace ConsoleApplication2
{
   
        
public class CTester
        
{
            
public CTester()
            
{
                a 
= 10;
            }

        

            
public void test1()
            
{
                a 
= (a - 0.0001* 1.0001;
            }

            
private double a;
            
public double geta() return a; }
        }


   


    
class Program
    
{
        
private string test1()
        
{
            
int now = System.Environment.TickCount;
           
            
for (int i = 0; i < 1000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    CTester aTest 
= new CTester();
                    aTest.test1();
                    
                }

            }


            
string time = (System.Environment.TickCount - now).ToString();
            
return time;
        }

        
static Hashtable table = new Hashtable();
        
private string test3()
        
{
            
int now = System.Environment.TickCount;
           
            
for (int i = 0; i < 1000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    Type theTest 
= null;
                    
if (table.ContainsKey("ConsoleApplication2.CTester"))
                    
{
                        theTest 
= table["ConsoleApplication2.CTester"as Type;
                    }

                    
else
                    
{
                        theTest 
= Type.GetType("ConsoleApplication2.CTester");
                        table.Add(
"ConsoleApplication2.CTester", theTest);
                    }

                    ConsoleApplication2.CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
                        , 
nullnullnullas ConsoleApplication2.CTester;
                    theobj.test1();
                }

            }


            
string  time =(System.Environment.TickCount - now).ToString();
            
return  time;
        }

        
private string test2()
        
{
            
int now = System.Environment.TickCount;
            
for (int i = 0; i < 1000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    Type theTest 
= theTest = Type.GetType("ConsoleApplication2.CTester"); ;
                    ConsoleApplication2.CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
                        , 
nullnullnullas ConsoleApplication2.CTester;
                    theobj.test1();
                }

            }


            
string  time =(System.Environment.TickCount - now).ToString();
            
return time;
        }

          
static object InvokeMehod(string FileName,
            
string MethodName,
            
object[] Args)
        
{
            Assembly a 
= Assembly.LoadFrom(FileName);


            MethodInfo method 
= null;
            Type HereType 
= null;
            
foreach (Module m in a.GetModules())
            
{
                
foreach (Type t in m.GetTypes())
                
{

                    
foreach (MethodInfo mInfo in t.GetMethods())
                    
{
                        
if (mInfo.Name == MethodName)
                        
{
                            ParameterInfo[] pInfo 
= mInfo.GetParameters();
                            
if (pInfo.Length == Args.Length)
                            
{
                                
bool same = true;
                                
for (int i = 0; i < pInfo.Length; i++)
                                
{
                                    
if (Args[i] != null && pInfo[i].ParameterType != typeof(object)
                                        
&& pInfo[i].ParameterType != typeof(object[]))
                                    
{
                                        
if (pInfo[i].ParameterType != Args[i].GetType())
                                        
{
                                            same 
= false;
                                        }

                                    }

                                }

                                
if (same)
                                
{
                                    HereType 
= t;
                                    method 
= mInfo;
                                }

                            }

                        }


                        
if (method != null)
                        
{
                            
break;
                        }

                    }


                    
if (method != null)
                    
{
                        
break;
                    }

                }


                
if (method != null)
                
{
                    
break;
                }

            }


            
if (method == null)
            
{
                
//Log.LogException(typeof(Excute), "没有发现:" + FileName + "/" + MethodName, new Exception("没有发现:" + FileName + "/" + MethodName));
                return null;
            }


            
object ins = null;
            
if (!method.IsStatic)
            
{
                ins 
= a.CreateInstance(HereType.FullName);
            }

            
object RetObject = method.Invoke(ins, Args);
            
return RetObject;
        }

    

        
private string test5()
        
{
            
int now = System.Environment.TickCount;
            
for (int i = 0; i < 1000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    InvokeMehod(
@"D:\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2\bin\Debug\ClassLibrary1.dll""test1"new object[] { });
                }

            }


            
string time = (System.Environment.TickCount - now).ToString();
            
return time;
        }

        
static void Main(string[] args)
        
{
            Program p 
= new Program();
            
string ticks = p.test1();
            Console.WriteLine(
"用编译器执行:"+ticks);
            
string t = p.test2();
            Console.WriteLine(
"用反射执行"+t);
            
string t1 = p.test3();
            Console.WriteLine(
"优化之后的反射:"+t1);
            
string t2 = p.test5();
            Console.WriteLine(
"加载程序集并反射:"+t2);
            
if (ticks.ToString() == "0")
            
{
                Console.WriteLine(
"反射/编译: 不在一个级别上面");
            }

            
else
            
{
                Console.WriteLine(
"反射/编译 =" + (Convert.ToInt32(t) / Convert.ToInt32(ticks)).ToString());
            }

     
            
if (ticks.ToString() == "0")
            
{
                Console.WriteLine(
"加载程序集并反射/编译: 不在一个级别上面");
            }

            
else
            
{
                Console.WriteLine(
"加载程序集并反射/编译 =" + (Convert.ToInt32(t2) / Convert.ToInt32(ticks)).ToString());
            }

           

            Console.WriteLine(
"加载程序集并反射/反射 =" + (Convert.ToInt32(t2) / Convert.ToInt32(t)).ToString());
           
            Console.Read();
        }

    }

}

测试结果为:

638倍的性能损失,不知道算大算小,反正项目经理说无所谓。
赫赫,无(。。)者无畏

posted @ 2006-08-10 14:50  Robin Zhang  阅读(5839)  评论(41编辑  收藏  举报