提高程序性能的小细节--以后会不断添加小技巧
2013-06-22 11:12
204 查看
第一大类:简化循环
小到一个内网扫描工具,大到一个GIS系统,大大小小的软件系统中都会用到很多循环,计算机能够比人脑显得有能力的最重要的一点就是:计算机软件可以任劳任怨的去执行枯燥的类似遍历的循环。所以任何写软件的编程人员都会涉及到设计循环结构的问题。一个好的循环结构能够在解决相同问题的同时节省更多的时间或空间。很多人会自然的想到各种排序、查找算法的设计问题,因为相关的大神级文档遍布网络,本文就不赘述,只是总结一些代码细节的内容,旨在阐述“代码方案”的决策对于程序性能影响。
案例1:不要把已知特例放到循环里面去判断
有下列代码,源码的作者为了简化代码的书写,将一个已知特列的判断放到了循环中。此循环是一个经典的遍历循环,for中语句的执行次数为framePosition.Count()次。
如行7、17所示,i == 0 ? Canvas.GetTop(player) : framePosition[i].Y;为三目运算符,相当于以下代码:
案例2 别忘了关键字“break”
上面段代码演示了一个经典的遍历查找算法,代码最优情况下运行1次,最坏情况下运行count次,不过我说的是设计思路,设计时我们是这样想的,然而实际这段代码每次查找都会执行count次。我们有时候在工作中,繁忙的任务和逼人的进度往往会使在小公司工作的我们只关心代码是否能够正确的安装设计逻辑去执行,而疏忽了某些能提高性能的细节。 上面这段代码,如果集合中包含超出满足条件的结果,肯定能被找出,但是效率确实低下的。尤其是在有序队列中查找的时候(当然应该是一2分,而有时候调用者并不知道数据已经被拍序),次算法效率低下的几率更高。 只需添加一句break语句,就这么简单,便能提高效率。
[b]案例3 循环中的判断语句[/b]
假设有这样的语句:
其中Address表示设备的地址,是一个16位的无符号整形值,分开存在Address_Hight和Address_Low里面(这种方式在通信类程序里面常常用到)。
在通信事物处理层常常会见到以下类似代码,用于比对“设备返回信息中包含的设备自身的地址”和“系统存储的会话列表中的设备地址”
但是实时上设备的地址一般是从1开始递增的,一般很少有设备用到超过255以上的地址,所以地址的高位一般都为0,而我们知道在逻辑与运算中,if(X1&&X2)这样的语句,总是会先检测X1是否为ture,然后再检测X2是否为ture,如果都为ture方可进入if的内部。如果X1为ture的概率远大于X1位ture的几率,那么把X2写在前面会更合适一些。对应到本例应该写为if(X2&&X1)更为合适
if(Address_Low_FromHW==myList[i].Address_
&&LowAddress_Hight_FromHW==myList[i].Address_Hight)
而如果使用X1||X2逻辑或计算时,应该把为ture几率大的表达式放在最前面,这样可以减少代码检测的次数,从而提高性能。
[b]案例4 循环每次递增2次的写法[/b]
[b]下面的代码是要生成一行两列的html代码:[/b]
小到一个内网扫描工具,大到一个GIS系统,大大小小的软件系统中都会用到很多循环,计算机能够比人脑显得有能力的最重要的一点就是:计算机软件可以任劳任怨的去执行枯燥的类似遍历的循环。所以任何写软件的编程人员都会涉及到设计循环结构的问题。一个好的循环结构能够在解决相同问题的同时节省更多的时间或空间。很多人会自然的想到各种排序、查找算法的设计问题,因为相关的大神级文档遍布网络,本文就不赘述,只是总结一些代码细节的内容,旨在阐述“代码方案”的决策对于程序性能影响。
案例1:不要把已知特例放到循环里面去判断
有下列代码,源码的作者为了简化代码的书写,将一个已知特列的判断放到了循环中。此循环是一个经典的遍历循环,for中语句的执行次数为framePosition.Count()次。
for (int i = 0; i < framePosition.Count(); i++) { //加入X轴方向的匀速关键帧 LinearDoubleKeyFrame keyFrame = new LinearDoubleKeyFrame(); keyFrame.Value = i == 0 ? Canvas.GetLeft(player) : framePosition[i].X; //平滑衔接动画 keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i)); keyFramesAnimationX.KeyFrames.Add(keyFrame); //加入X轴方向的匀速关键帧 keyFrame = new LinearDoubleKeyFrame(); keyFrame.Value = i == 0 ? Canvas.GetTop(player) : framePosition[i].Y; keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i)); keyFramesAnimationY.KeyFrames.Add(keyFrame); }
如行7、17所示,i == 0 ? Canvas.GetTop(player) : framePosition[i].Y;为三目运算符,相当于以下代码:
if( i == 0 ) { Canvas.GetTop(player) : }else { framePosition[i].Y; }
程序这样的写的结果是,无论framePosition.Count()的值为1还是为N,行7、17的代码都会执行,但是从业务层面分析,“Canvas.GetTop(player) ”这句代码只需要在i==0时执行才是合理的,也就是说当0<framePosition.Count()<n时,所有的if判断都是没有意义的。经过这样的分析,可以将i==0的条件作为一个特列来处理,让循环从1开始,这样虽然多写了几行代码,但是会令代码得到很好的性能改善,何乐而不为呢?
总结:尽可能的减少循环里面的已知特例判断。
案例2 别忘了关键字“break”
int result=-1; for(int i=0;i<count,i++) { if(count[i]==X) result=count[i]; }
上面段代码演示了一个经典的遍历查找算法,代码最优情况下运行1次,最坏情况下运行count次,不过我说的是设计思路,设计时我们是这样想的,然而实际这段代码每次查找都会执行count次。我们有时候在工作中,繁忙的任务和逼人的进度往往会使在小公司工作的我们只关心代码是否能够正确的安装设计逻辑去执行,而疏忽了某些能提高性能的细节。 上面这段代码,如果集合中包含超出满足条件的结果,肯定能被找出,但是效率确实低下的。尤其是在有序队列中查找的时候(当然应该是一2分,而有时候调用者并不知道数据已经被拍序),次算法效率低下的几率更高。 只需添加一句break语句,就这么简单,便能提高效率。
int result=-1; for(int i=0;i<count,i++) { if(count[i]==X) { result=count[i]; break; } }
[b]案例3 循环中的判断语句[/b]
假设有这样的语句:
Class MyDataRowCommunicating { public byte Address_Hight; public byte Address_Low; .... }
其中Address表示设备的地址,是一个16位的无符号整形值,分开存在Address_Hight和Address_Low里面(这种方式在通信类程序里面常常用到)。
在通信事物处理层常常会见到以下类似代码,用于比对“设备返回信息中包含的设备自身的地址”和“系统存储的会话列表中的设备地址”
List<MyDataRowCommunicating> myList= new List<MyDataRowCommunicating>(); .... byte Address_Hight_FromHW=GetAddressHight(); byte Address_Low_FromHW=GetAddressLow(); for(int i=0;i<myList.count;i++) { //我们会不加思索的这样来写这个判断语句 if(Address_Hight_FromHW==myList[i].Address_Hight &&Address_Low_FromHW==myList[i].Address_Low) { .... } }
但是实时上设备的地址一般是从1开始递增的,一般很少有设备用到超过255以上的地址,所以地址的高位一般都为0,而我们知道在逻辑与运算中,if(X1&&X2)这样的语句,总是会先检测X1是否为ture,然后再检测X2是否为ture,如果都为ture方可进入if的内部。如果X1为ture的概率远大于X1位ture的几率,那么把X2写在前面会更合适一些。对应到本例应该写为if(X2&&X1)更为合适
if(Address_Low_FromHW==myList[i].Address_
&&LowAddress_Hight_FromHW==myList[i].Address_Hight)
而如果使用X1||X2逻辑或计算时,应该把为ture几率大的表达式放在最前面,这样可以减少代码检测的次数,从而提高性能。
[b]案例4 循环每次递增2次的写法[/b]
[b]下面的代码是要生成一行两列的html代码:[/b]
for (int LCount = 0; LCount < XNList.Count; LCount++) { //i执行的内容 img_src = XNList[LCount].Attributes["textStr"].Value; href = XNList[LCount].Attributes["href"].Value; templateBuilder.Append("<a href=\"" + href + "\" style=\"border:hidden\">" + img_src + "</a>"); //i加一 LCount++; //i+1后执行的内容 img_src = XNList[LCount].Attributes["textStr"].Value; href = XNList[LCount].Attributes["href"].Value; templateBuilder.Append("<a href=\"" + href + "\" style=\"border:hidden\">" + img_src + "</a></br>"); }
相关文章推荐
- 一些小细节让你的Java程序性能大幅提高
- 提高程序性能、何为缓存——从存储器结构说起
- 同大家分享一些java程序性能提升的一些小技巧
- 如何优化JAVA程序开发,提高JAVA性能
- 程序的性能优化之代码上的细节优化
- [C/C++]_[初级]_[如何编写简单有效代码,提高程序运行效率和性能]
- 小议Function.apply()之二------利用Apply的参数数组化来提高 JavaScript程序性能
- 如何优化JAVA程序开发,提高JAVA性能?
- 巧用缓存提高asp程序的性能
- 巧用缓存提高asp程序的性能
- 用缓冲技术提高JSP程序性能和稳定性
- 性能提高小技巧
- [转]提高精简框架集程序的性能
- 使用内存映射文件来提高你程序的性能
- 记录一些算法(以后会不断添加)
- ASP.NET小技巧:重写ViewState的存储目的地,以提高页面性能
- 提高博客网站程序性能的十条建议
- [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)
- 分享Web应用运行的细节问题:预编译提高网站性能、跟踪用户习惯和解决线程同步
- 不断优化配置,逐步提高性能——我的一次性能测试经历