反射(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
, null, null, null) as 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
, null, null, null) as 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();
}
}
}
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
, null, null, null) as 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
, null, null, null) as 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倍的性能损失,不知道算大算小,反正项目经理说无所谓。
赫赫,无(。。)者无畏
作者:jillzhang
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。