反射(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倍的性能损失,不知道算大算小,反正项目经理说无所谓。
赫赫,无(。。)者无畏

作者:jillzhang
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2006-08-10 14:50 Robin Zhang 阅读(3027) 评论(41)  编辑 收藏 网摘 所属分类: 系统架构

  回复  引用  查看    
#1楼[楼主]2006-08-10 14:54 | jillzhang      
而且由于GAC的存在,直接编译运行的第一次之后大概10-20次均为0
  回复  引用  查看    
#2楼2006-08-10 15:36 | Ring      
程序对性能的影响主要看什么场合。
  回复  引用    
#3楼2006-08-10 15:50 | lankey[未注册用户]
经过实际项目验证,一套ERP/一套别的系统,证明反射的性能还是可以接受



  回复  引用  查看    
#5楼[楼主]2006-08-10 16:00 | jillzhang      
@lankey
你们的项目不知道要害死多少客户。
600倍的差距,还不以为然,人家的服务器可以跑600人,你的跑1个,你看客户找你不?
用还是可以,不过要适量,所有都建立在反射上面,差距不用头都能像出来

  回复  引用  查看    
#6楼2006-08-10 16:04 | Ring      
@木野狐
里面的文章的链接已经打不开了。

  回复  引用  查看    
#7楼[楼主]2006-08-10 16:07 | jillzhang      
即使用也要优化,也绝对要优化。
至于说行的,我不说别的了。只能说明不负责的系统必然会有不负责系统的结果而已。
也许现在的系统,还跑得好好的。等跑不动的时候,别又找个借口重做一个,然后收人家钱就行了。

  回复  引用  查看    
#9楼[楼主]2006-08-10 16:12 | jillzhang      
@Ring
就是因为有这样的思想,所以才有成千上万的系统里出现存储着成千上万条按照值来查找的顺序集合。

  回复  引用  查看    
#10楼[楼主]2006-08-10 16:14 | jillzhang      
例外单纯的使用反射性能损失在100倍左右,但通过加载dll程序集反射,损失在600倍,看好了。600倍
  回复  引用  查看    
#11楼2006-08-10 16:16 | henry      
楼主有没有测试一下处理一个page的生命周期要多长时间?
一个业务逻辑的操作(存在反射)又要多长时间。
适量使用获取程序灵活我觉得是个好事情。
AppServer的成本也不是很高。




  回复  引用  查看    
#12楼[楼主]2006-08-10 16:27 | jillzhang      
看来支持者真的有一批。
灵活性一定要通过反射来实现么?
2.页面处理周期有多长不是你的问题,是ms的问题。
的确,在类似ndoc这样的程序里面,反射没有任何问题。
关键是这个具体环境如何划分。你能把握住么?
这不是性能与扩展的平衡问题。而是一个设计者的考虑问题的全面问题。
如果性能和扩展倍数关系在1-5倍,即为了提高1倍的扩展,需要5倍的性能损失,那么这样叫平衡。但600还说是平衡,牵强与否,明白人自己知道。

  回复  引用  查看    
#13楼2006-08-10 16:46 | henry      
这样说不合理,要从系统整体效果来看。如果真的差这么远不要说给客户,就是你们自己测试都会疯掉!
你并不能说反射效率这么低就完全否认它,难道DataGrid在处理ViewState不低吗?DataGrid的数据绑定过程不低吗?为什么还是有这么多人用它?
难道你们的处理页面使用反射占整个处理周期90%,如果是这样我会把那个设计者砍死!如果只占百分之几那我并不认为有什么问题,因为还有更多的地方要关注。

补充:不要把系统所有性能问题归究于反射。除非你能保证其它代码都写得很完美!

  回复  引用  查看    
#14楼[楼主]2006-08-10 16:55 | jillzhang      
那么更多的地方肯定还有更多这样类似的问题存在,不能说我们熟悉Arraylist,方便使用就用它存储大量的按值查找的数据。
我敢说有这样的思想的,一般说性能那里也不会考虑到。因为首先自己先给自己找了条大大的借口,所以这样的思想设计出来的系统往往是数据处理长,页面处理长,逻辑运算长,那么真个系统性能就下来了。10倍-20倍算是设计失误,顾全大局,几百倍算是什么呀?
你说还有其他的事情要做,其他事情你会考虑到性能么?
首先性能是一种功能。在设计的时候就应该考虑到。

  回复  引用  查看    
#15楼[楼主]2006-08-10 16:56 | jillzhang      
再说我们的系统是b/s下的
  回复  引用  查看    
#16楼2006-08-10 17:21 | 小陆      
只看这个测试结果不能说明问题,从文章中我无法判断你的试验情况和实际的项目情况有多大程度的相似。

反射的效率低,这是肯定的。重点问题在于是不是真的频繁的使用了反射。比如struts框架,对于每个Action的实例都是通过反射的形式建立的,但是建立这个实例之后,就把他缓存下来了,以后再调用就直接拿来用了。所以他的效率比起直接调用差不了多少,又充分利用了反射的灵活性。
重要的不是用不用反射,而是怎么用,好的设计可以扬长避短。反之如果设计是糟糕的,好的技术也无法起到预想的效果。

另外,清晰的逻辑结构是可以提升系统性能的,尽管他表面上看来是增加了流程的环节,但是随着需求的扩大,效率的下降是缓慢的,甚至不会下降。

从理论上说,UI直接操作DB效率是最高的,但是实际上,这样的系统经过一段时间的发展以后,复杂程度会超过控制,效率一般都会急剧下降。

  回复  引用  查看    
#17楼2006-08-10 17:47 | 双鱼座      
@jillzhang
楼主对反射的看法偏颇,很多结论都是先下了然后再去证实的。虽然你的测试结果是可信的,但是没有任何实用价值。说到这我想起一个笑话:有个人开着车迷路了,问路人“我在哪”,路人答“你在车上”。于是此人对路人说“你一定是搞IT的”,因为IT人总是定义一些非常正确却没有任何价值的结论。路人也对此人说你一定是项目经理,因为项目经理通常都是连自己在哪儿都不知道还总是抱怨别人。
1.直接调用与加载后的调用相差600多倍,我觉得已经非常小了。事实上耦合方式的加载也是需要代价的,只是没有被你记录下来,而通过反射加载碰巧被你记录了。这两个记录拿到一起比较显然不公平。在一个dll被加载后,如果将该Assembly保存起来以备下次使用,速度一定快很多倍。
2.用反射调用方法其实也是一样,你可以将每个MethodInfo保存起来以备下次使用的。这样只需要一次反射然后多次Invoke,速度和卢彦文章中的结果应该相差不多。
3.如果总是象你测试中的那样用反射,那个反射的技术完全没有必要存在。据陈榕讲,Java中首次使用反射技术,导致欧盟技术委员会废弃了才发布一年的标准,这个事实对于这个委员会来说是很丢脸的事情,但是这个委员会还是采用了反射的方案,足以说明反射的价值。如果说你的某个系统执行了10000个OpCode指令,其中有一个指令是用于反射,即使这个指令比直接调用慢了600倍,如果是为了换取比较高的灵活性,我认为也是值得的。
4.在一个系统中分发多少个dll是由应用来决定的,而不是拍脑袋去想数量是不是过多。如果dll太多并且是频繁的穿插引用,合并dll是必要的,但肯定不是和windows去依据复杂性来比较dll的个数。一般来讲,互不耦合的dll越多,反而说明系统的可维护性越好而不是你说的越糟。替换一个dll比替换两个dll还是要简单一点。但是替换一个小的dll比替换一个大dll更简单。
5.还是建议你看一下《最大化.net性能》一书,书中的测试不仅公正,而且有理有据。

  回复  引用  查看    
#18楼2006-08-10 19:08 | Ring      
看来作者钻了"性能"的牛角尖!

我想说两点:
1.如果你的系统瓶颈在性能上, 那好,千万要优化你的现在程序的性能, 看看是否该采用别的方法替换使用反射造成的性能损失. 不要说性能相差几十倍,哪怕对性能的影响只有区区1,2倍,那还是要对此开刀的。

2.如果你的cpu,内存资源足以运行你当前的系统, 那么就使用反射吧. 反射带来的灵活性将会使你裨益.

上面有位朋友也已经说了,在程序的灵活性,扩展性以及性能等方面造成冲突时,就需要看情况取舍了。

为什么我们做项目要采用分层思想? 分层不是有损于性能吗? 因为采用分层带来的程序可扩展以及可复用的好处要远远高于因此带来的性能损失!

  回复  引用  查看    
#19楼[楼主]2006-08-10 19:10 | jillzhang      
@双鱼座
首先感谢你精辟的阐述。

这篇文章其实来自于和项目经理的一次争论,因为你们并不是了解我们这个项目,所以也情有可原。首先作为一个项目负责人,最应该把握的是某个技术存在那个优点,存在那些缺点,就拿反射来说,他的优点在于能够提高应用程序的灵活性,但缺点是性能有所消耗,本来性能和灵活就是此消彼长,最后选择谁也无可厚非。但是无视某种技术的缺点,丝毫不加以考虑,势必会给项目造成坏的影响。其实我也是一直在使用工厂模式+反射来实现多库的支持。但是我绝对会像你所说加上高速缓存。测试的数据你也可以看出,优化之后,效果还是比较明显,可以说基本接近我所说的性能在10倍左右的差距的论断。但是,作为一个项目的负责人,由于个人原因以前的确忽视了此处问题的存在,这也是无可厚非,最让人生气的是当我提出来问题的时候,不是说细心的思考或者测试,而是试图维持自己的错误观点,今天我将测试程序演示看,看到如此大的差距,仍然坚持反射不会影响系统的性能。这样的态度让人实在不爽。
所以也说出了一些比较偏激的观点,首先纠正自己这方面的不足,以防对他人造成误导。
使用反射,我不反对,我所反对的是固步自封的态度和不严谨设计方法。因为到目前为止,还是坚持不用优化。坚持的认为反射性能好,甚至错误的认为,当执行Main函数的时候,也是根据反射来查找。
最反对的就是别人一说自己的不行,马上找出一大堆毫不相干的理由来驳斥甚至批评人。当然我上面的回复的确也存在这个问题。但我做人的态度是人家提出问题首先要思考一下问题是否存在。不是为了自己的一点自尊掩盖视听。
其实,很多负责人都是自以为是,自己也深有体会,但事实上也许正是这些导致自己的水平不能有所提升。

  回复  引用  查看    
#20楼[楼主]2006-08-10 19:16 | jillzhang      
的确有时候我钻牛角尖,但我觉得在我上述描述的问题中,我钻的值得,首先我现在不是自己带项目,那么这个项目中的经验教训,我会吸取。如果不钻,技术恐怕只能停留在一个层面上。

  回复  引用  查看    
#21楼[楼主]2006-08-10 19:23 | jillzhang      
我到现在都奇怪,为什么有人写程序写了4年多,还带项目,却连一些基本的数据结构常识i都不懂。甚至连存储过程都不晓得。
当然可能他懂得其他很多,但是我觉得也不会太多。就像你天天拿着筷子吃饭一样,最后人家问你筷子是什么样子的,你竟然不知,光是知道吃饭有什么用。每天都说自己的系统多多好,而不是进行横向的比较。写了好几年代码,结果做了个系统还是照样被人SQL注入。这样难道就是正确的么>
钻看怎么钻而已,如果是钻研的钻,岂不是无可厚非

  回复  引用  查看    
#22楼2006-08-10 20:44 | idior      
reflection的性能要看应用场景。
比如在c/s中,你在client端偶尔使用反射 那就是1000倍也没多大问题。
如果在server端不是每个用户都会产生反射调用的代码,那问题也不大。

  回复  引用  查看    
#23楼2006-08-10 21:42 | Ying-Shen      
Reflection会有不小的性能代价,但并不能简单的说
系统性能会因为使用反射而造成很大损失。
其实你的比率关系的公式是这样的:
(反射调用时间+函数执行时间)/(直接函数调用时间+函数执行时间)
也就是说,当函数执行时间可以忽略不计的时候,这里近似等于反射调用与直接调用时间的倍数。
因此也有一种实际情况是函数执行时间远大于反射调用时间,这种时候无论是直接调用还是反射调用对函数执行时间而言都是可以忽略不计的。
这种情况在测试中很少能够看到,因为测试函数过于简单,不过对于实际系统,这种情况的发生几率大得多,I/O文件操作,数据库查询以及一些复杂的算法等都很费时间。而且根据你的说法反射用于调用assembly中的方法,我想反射调用应该也就一次,而整个方法的执行过程中,前述的文件和数据库操作可能会有2,3次或更多吧。

因此反射是不是会成为系统的性能瓶颈这个还很难说。

  回复  引用  查看    
#24楼2006-08-10 23:00 | 双鱼座      
@jillzhang
听你一讲,你的项目经理可能有点心胸狭窄,这样的人很多,让人也感到很无奈。不过我认为比较好的方式不是针尖对麦芒,尽量避免正面冲突。对某些具体技术细节的争执很有意义,但更多的争论却是无谓的。

  回复  引用    
#25楼2006-08-11 09:19 | 立特拉萨[未注册用户]
其实大家仔细看看。。LZ不是对反射有意见, 而是对他的项目经理有意见。
看来reflection吃了死猫拉。。。

  回复  引用    
#26楼2006-08-11 10:23 | Mok[未注册用户]
Loading assembly from file will cost some time. When the assembly is loaded into App Domain, u can load it from the App Domain rather than everytime load from file (which involved IO). Hope can help.
  回复  引用  查看    
#27楼2006-08-11 10:23 | 笨笨熊      
@jillzhang
我觉得Ying-Shen的分析很有道理,你的测试函数只能单纯地测试出反射调用和直接调用之间的差距,但是ERP毕竟是一个很大的系统,影响性能的地方想必多得很,这个差距放在其中能不能成为瓶颈真是很难说得事,也许提高性能还能有很多可以下手的地方。
PS:不过话说回来,这种差距在设计时能考虑到是最好的,至于你的项目经理不采用,那是他的事了。对领导有意见是正常地,但是对着他表现出来是不明智地:)

  回复  引用    
#28楼2006-08-11 10:28 | Mok[未注册用户]
@Mok

something like this
myClass my = null;
Type cType = Type.GetType(classname,false,true);
if (cType == null)
{
Assembly assembly = Assembly.Load(mydllfilename);
cType = assembly.GetType(classname);
}
my= (myClass)Activator.CreateInstance(cType);

  回复  引用  查看    
#29楼2006-08-11 10:57 | XiaoHui      
@Ying-Shen
@笨笨熊

个人比较赞同他们的观点, 片面放大了直接调用的优势, 难道整个项目就单靠一个直接调用和一个反射调用的比较来评价整体性能?其实反射带来的灵活性是大家有目共睹的.

  回复  引用  查看    
#30楼[楼主]2006-08-11 11:00 | jillzhang      
不错,又见识了不少。
不过,对于表现不表现,没必要掩饰,我又不是靠他吃饭。
把我惹毛了,谁吃亏也不一定。反正我肯定吃不亏。大不了走人而已。再说这样走人一点都不丢人,我也不会觉得自己个性,本来就是双向的选择而已。

  回复  引用  查看    
#31楼[楼主]2006-08-11 11:10 | jillzhang      
看来我惹来公愤了。其实立特拉萨说的对。因为我发表这篇随笔的时候意见很大,难免对反射有了错误理解。
反射的确存在性能问题,这个市不争的事实,大家谁可以测试出来相反的结果,请指教。
在具体系统中,反射还是可以应用,甚至可以推广应用的。
但是设计的时候,考虑其性能问题也是必须的。

  回复  引用    
#32楼2006-08-11 11:25 | sfotware[未注册用户]
@jillzhang
遇到点问题就动不动走人,这可不好。 想必你是年轻人,说话做事太冲动阿!!

  回复  引用    
#33楼2006-08-11 11:25 | Yuanlm[未注册用户]
可以在系统初始化时通过反射把相关信息缓存起来,这样灵活性和性能可以兼得了。
  回复  引用    
#34楼2006-08-11 11:27 | sfotware[未注册用户]
在现实生活中,谁不会遇到问题呢?谁不遇到受气的时候呢? 小伙子不能意气用事阿!
  回复  引用  查看    
#35楼2006-08-11 12:27 | Cure      
现在的项目越来越复杂,为了灵活性,就要解耦,解耦就造成了程序集数量增多,要把大量的程序集组合起来,就要可插拔,就需要配置,而可配置必然导致使用反射。
  回复  引用  查看    
#36楼2006-08-11 16:33 | koenemy      
别用console做测试
用form测试一下
打开form点一下测试按扭,看看数据是多少。。
别关程序,在点一下测试按扭,看看数据是多少。。

也就首次运行的时候费点劲,后来差不了多少了。。.net机制嘛。反射应该不太差

  回复  引用    
#37楼2006-09-07 10:17 | kardonhost[未注册用户]
J2EE 服务有多少不是反射来调用服务的,spring等等都是,性能也没有底到哪儿去。。 要松藕就的反射。
  回复  引用  查看    
#38楼[楼主]2006-09-07 10:20 | jillzhang      
@kardonhost
人家一定会加上Cache机制的。
你看看我的测试数据就知道,加上Cache的结果还可以!
不过不加cache直接调用,就像机器裸奔,硬说自己不会中病毒一样!

  回复  引用  查看    
#39楼[楼主]2006-09-07 10:21 | jillzhang      
另外在同一AppDomain 下的Assembly,比调用不在同一AppDomain下的性能要好
  回复  引用  查看    
#40楼2008-06-06 13:31 | 守矢      
--引用--------------------------------------------------
jillzhang: @kardonhost
人家一定会加上Cache机制的。
你看看我的测试数据就知道,加上Cache的结果还可以!
不过不加cache直接调用,就像机器裸奔,硬说自己不会中病毒一样!
--------------------------------------------------------

一定会用缓存的,并且缓存之后只有第一次加载慢一些,缓存的是操作的结果,这样不会存在10W次的反射,另外程序集可以加载到缓存中,在命令提示中可以做到,该程序据依然可以被缓存。

微软的MVP对反射进行了测试,对1W次操作,性能相差2-3倍。(网址忘记了,我进行过咨询)

直接使用发射,没有任何措施,当然是慢,因为普通人拿着倚天剑往往是在伤害自己,因为他无法控制,最终被别人抢走。

合理的利用反射式我们所需要的,滥用任何代码对于性能都有很大的损耗。

  回复  引用  查看    
#41楼2008-06-06 13:34 | 守矢      
我的机器裸奔了4年,中过几次毒,但我保证了性能,1.8CPU,256内存跑的也很快,最近根本没有中过毒,因为我有防范的措施。

我不使用杀毒软件是适当的。

如果你天天上色情网站,那么你必须安装杀毒软件。可是我不上,就像我不滥用反射一样。




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 473326 +Ru1jF9Oy3E=



相关文章:

相关链接: