当前位置: 首页 > 科技观察

反射真的会降低程序的性能吗?

时间:2023-03-16 00:36:16 科技观察

前两天写了这篇文章《从把三千行代码重构成15行代码谈起》。看到评论里有同学的回复还在质疑反思的表现。看来程序使用了反射。这就像驾驶拖拉机。本来,我觉得这个话题没什么好讨论的。网上已经有太多文章讲这个问题了。如有疑问,可上网查找相关文章进行参考。不过,我记得我第一次编程的时候,也遇到过这种困惑。网上搜了一下,从各个角度进行了解释,基本解释了本质,但是还是有很多人不理解。我将从这里开始。再说说我的观点。毫无疑问,反射比直接调用慢,我的文章也不是要证明反射有多高效。现在快递很流行,那我们就举个快递的例子吧。如果快递员在你住的小区,那么你报一个地址:xx楼xx,快递员就可以马上知道你在哪里,直接上门;但是,如果快递员是第一次来你家,是不是要先查百度地图,看怎么开车,到的时候还要问物业xx楼怎么找社区,然后,他可能会在楼下转两圈才到。到了你家门口。让我们看看上面的场景。如果快递员不熟悉你的社区,他会放慢速度吗?他的时间主要花在搜索百度地图和询问物业上。好的,反应也一样,因为我事先不知道任何事情,所以我必须花时间寻找其他来源才能找到你。有兴趣的可以查看MetaData的反射实现原理和相关概念。反射比直接调用慢多少?嗯,我们知道反射肯定是慢的,那么反射是不是就没法用了呢?有些人一听到slowness,就很着急的下结论,说反射不行,或者不能用。但是,同学,反射比直接调用慢多少呢?你能做到吗?能给我实际数据吗?很多人其实对于性能只有一个模糊的概念,没有数值的支持。之前帮同事找了一个动态解析表达式的类库。他认为这不是很容易使用。他很聪明,很快发现DataTale.Compute可以用来实现公式的动态解析。我问他,这个方法和我给的类库在性能上有什么区别?他跟我说这个已经很快了,不到1秒就可以执行完。我一听,就觉得不对劲。你的思维还停留在第二层。你跟我说什么性能?如何判断一个函数的性能好坏?因为函数的执行速度太快,所以需要一个减速镜,这样就可以捕捉到他的速度。怎么做?只有把一个函数执行一百万次、千万次,才能真正了解一个函数的性能。也就是说,如果要评判性能,不能停留在秒或毫秒的概念上。你必须用另一个概念来代替它才能知道真正的表现。结果我同事把这两个方法执行了100w次。确实,我提供的类库比他的快了8秒。好了,现在拿我前两天提供的工厂方法来测试一下。CodeTimer的实现参考了赵大神的文章《一个简单的性能计数器:CodeTimer》:测试方法如下:[测试]publicvoidTestReflector(){CodeTimer.Time("Direct",100*10000,()=>{varinstance=new连接测试();});CodeTimer.Time("Reflect",100*10000,()=>{this.GetType().Assembly.CreateInstance("TestPropertyGrid.ConnectionTest");});}测试结果如下:DirectTimeElapsed:25msCPUCycles:57,582,163Gen0:14Gen1:0ReflectTimeElapsed:3,231msCPUCycles:8,001,720,795Gen0:269Gen1:1看,我们的放大镜起作用了现在,我们大概可以画出这样一个结论:执行100万次时,反射大概会拖慢直接调用50~100倍。100次,乍一看,差别很大,但是,前面说过了,不要急于下结论,得看前提。自古以来,我们都喜欢断章取义,比如“以德报怨”这句成语,就好像古人说的,遇到不好的事情,不能怨恨,要善待别人,当有人打你的左脸,你应该伸出右脸让他再打。但是这个成语实际上是什么样子的呢?或曰:“如何以德报怨?”曰:“何以报德?以德报怨,以德报德。”老的意思其实是别人对你好,你也要对人好。如果他惹你了你,去你的!看到这里,你是不是傻眼了?有多少情况需要考虑反射的影响?我认为这种情况是非常非常罕见的,我们大多数人根本不需要考虑这个。至于我上一篇文章提到的工厂,你的程序有多少实体,有100万吗?如果弹出窗口时您是新手,那么百万分之一秒的影响对您来说重要吗?另外,有人说,如果我真的有这种需求,我得new一个对象一百万次,那不还是很慢吗?有没有这种情况,有!比如我有100w条记录,需要取出来,然后通过反射赋值给一个Model类。但是对于这种情况,如果你真这么想,我只能说你在办公室坐久了,脑袋生锈了。是时候去爬山泡妞了。如果您需要对一个对象进行一百万次反思,那么您应该缓存该对象。就拿我们上面的例子来说,如果快递员给小区里的人送了一百万次还是不认路,他每次都得问百度地图,再问物业,你还没有给他开通。如果丢了,那你的脑袋要么就是个笑话,要么就是任性的有钱人。如果将上述代码缓存并执行一百万次,与直接调用有何不同?这里就不贴代码了,免得大家直接看结果没意思,自己敲代码,印象会更深。那么,有没有更快的方法,有。比如你的快递员开始用IPHONE4,现在你可以考虑给他买个6+。.net中提供了Emit的相关方法,让你反映更快。这里送大家一个通过反射快速给Model赋值的轮子“Dapper”,大家可以回家自己造了。应该在编程中使用反射吗?其实看了上面的文字,相信大家已经有了一个初步的判断,我的看法是:大部分情况下都可以使用反射。如果你认为你的程序因为反射而变慢,那么请使用减速镜仔细观察,看是否是反射的问题。如果你确定是反射的问题,那你就要仔细考虑一下,是你没有用好反射,还是像上面那个快递员,走了一百万趟,不认识路。***,如果你觉得性能还是不够,那我建议你升级一下硬件。硬件性能提升3%,还不如请个牛逼的工程师帮你做这种极致的优化。有句话我觉得“工程师比服务器贵很多”是真的。你要是还要和我比,那就没办法了。您的程序的性能要求超出了本文的范围。如果你真的有这样的需求,我觉得你没必要看我的文章,因为你已经足够好了,对系统语言有很深的理解。很多时候,我们会将程序的性能归结于编程语言,或者使用反射等技术,而很少关心自己的代码。这种心态会导致你的技术发展越来越慢,因为你失去了知识。渴望,一颗追求技术进步的心。请记住,很多时候,影响我们程序性能的是你的编程思想和编码态度!总结好了,说了这么多,估计很多人直接拖到文末默默点赞了,因为文中码了那么多字。那么,我就把这篇文章的精华献给你***:反射大概比直接调用慢50~100倍,但是你需要执行100万次才能判断一个函数的性能。如果你只是偶尔调用反射,你需要执行这个函数100万次甚至1000万次,请忽略反射对性能的影响如果你需要大量调用反射,考虑缓存。你的编程思维是限制程序性能的最重要因素。本文来自:http://www.cnblogs.com/marvin/p/ShallWeUseReflect.html