SmartPtr
本博客已搬至:http://www.cnblogs.com/baiyanhuang/
posts - 29,comments - 176,trackbacks - 0
By SmartPtr(http://www.cppblog.com/SmartPtr/)
  
    目前所做的项目,今年应该是第5release了, 走过了这5年的风风雨雨,中间几度更易开发人员,现在的团队与5年前的团队已是两个完全没有“交集”的团队, 这样必然导致我们对项目会存在很多的不理解,不理解其初衷,不理解其原始设计,不理解其代码。。。对一些不理解的地方不敢大动手脚,只能修修补补以完成需要的功能,其结局从开发角度看就是总体设计的缺失, 代码结构的混乱,从功能角度看就是容易出错,运行速度极慢。

    项目极其需要一次深入的代码重构与性能提升,而这都至少需要一个release的时间来做,对于代码重构, 从商业的角度来讲,是十分不可取的,一是其风险比较大,大刀阔斧的重构,如何保证软件的原有功能是个大问题; 而整整一个release的时间做重构,对于用户来讲,他拿到新的版本时,看不到任何新功能与提高,难道你告诉他,我们的代码结构现在很elegent。。。;但对于性能提升,现在是到了不得不做的地步,因为能够大幅度的提升性能,想必用户也能接受一个没有新功能的新版本。

    于是, 我们决定用一个release的时间来做性能优化。

    当然,我们不打算从学术的角度来考虑, 这个是O(n) 的算法,那个是O(nlgn) 的。。。; 也不打算从语言的角度来看待, 传引用要比传值快,类成员在初始化列表初始化。。。;当然, 并不是说这些不重要, 只是这些都应该是比较常见的,大家都应该清楚的事情, 也就是说我们假设我们的项目中不存在这种问题; 另外就是从语言角度来做的优化, 对我们的性能提升帮助不会太大。 我们会从一个宏观的,特定于我们项目workflow方面的角度来做优化。 主要包括以下几个方面:

     一、集中处理 (batch processing)

     把相关的操作集中起来处理, 从程序原理上来讲, 集中做相同的操作, 由于数据局部性的原理, 很多数据可以直接从cache中取得, 速度会比较快。 但我们主要考虑的还是另外一个因素,减少不必要的重复的初始化,假设将我有十个对象要update 一般情况下, 为了做update 我们必然要准备某些前提数据, 如果十个对象分别处理, 我就要初始化十次, 但如果我先把这十个对象收集起来,到最后一起处理, 最后只会初始化一次前提数据。 这对于update对象密集的情况十分有用。 当然, 这样我们也能有效的减少函数调用次数, 对性能提高也有不少的帮助。

     二、减少重复操作(初始化) (reduce repeated operations)

      重复操作, 一个是在有循环的时候, 我应该尽量把一些common的操作, 如一些输入数据的初始化提到循环外面来做,这在上面一点中也提到过。 二是对于一些全局的属性,操作等, 我们应该放在内存里,并提供一个全局访问点来直接得到, 而不是每次在需要的时候都去重新初始化一遍。 举个例子来讲, 每个application应该都有他自己的一些configuration, setting, 如果每次我需要这些信息的时候, 都从文件,或者注册表去读一次, 那就非常的浪费时间了, 尤其是涉及到I/O操作的时候。 当然, 这个有点像 cache的概念, 但是还远远不及。

     三、消除冗余操作 (avoid redundant operations)

    也许你不相信, 一个项目经过很多不同的人的开发, 由于理解上的误差,以及时间紧迫仓促完工,很多workflow上可能会都重复的操作, 仔细检察, 从全局上来考虑整个流程,你会发现, 其实我们做了很多不该做的事。

     四、cache机制 (cache mechanism)

     Cache的原理是用空间换时间, 当然,这个空间是指内存。我们把一些重要的中间信息放在内存中,以极大的提高查找,更新的速度。一般常用的数据结构就是map, 比如一个对象有长度这么一个属性, 但每次去得这个长度的时候都需要经过复杂的耗时的计算, 如果我们有些操作需要大量的使用到这个对象及其属性, 我们就可以建这样一个map: map<对象指针,长度> 这样每次用到时, 我只要到这个map中去查就可以了, 如果某个对象被更新了,我们需要更新这个map, 也就是说维护cache.

     五、延迟更新 (defer update)

      这是一个讲究策略的做法, 比如说我们的项目要在9.1号前demo给客户, 我们要写好代码,并维护好文档, 但是时间很急, 如果我们在9.1号前把这两件时都要做好,恐怕要疯狂加班了, 但是我们知道,客户只需要看到我们软件运行的效果, 文档他暂时并不关心, 那好吧, 我们9.1前就写代码, 文档就在demo后写好了。当然举这个例子的并不是鼓励大家先写代码,后补文档, 而是为了说明有些事情, 如果资源紧张, 我们可以把他分开看待,对于要的不急的那部分, 我们可以先不做, 等到时不忙了, 需要了的时候再做, 以缓解当前的紧张。 从代码角度举个例子, 假设我们有十条样条曲线需要更新, 更新可能包括样条线的方程,图形显示, 以及其长度等等, 如果我这些事情我一下子全做了, 用户可能要等很久, 但是我们知道, 用户做了这个操作, 他只需要看到图形上更新就可以了, 至于长度等什么的, 等他需要了, 或者空闲的时候,我们再给他更新, 这就让整个操作比较流畅了。

     这是我通过这个release对软件优化的一些想法,我相信现实中优化的方法是多种多样的,我希望这篇文章能够起到抛砖引玉的作用,希望大家能够提出自己的一些经验来共同分享。

posted on 2007-08-10 18:10 SmartPtr 阅读(1173) 评论(10)  编辑 收藏 引用

FeedBack:
# re: 我对软件优化的一些想法
2007-08-10 21:36 | missdeer
这文章总结得好  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-10 21:37 | pass86
最强的优化,还是算法优化。  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-10 22:43 | SmartPtr
因为算法上的优化一般都是为大家所知的, 所以在开发过程中也会特别注意, 因此这方面的优化并不是我们的侧重点  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-10 22:52 | aGAric
很好,不过不同情况下实践起来会有不同的重点  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-10 23:03 | SmartPtr
@aGAric
的确, 但这些应该是一些比较COMMON的想法, 也就是说我们在做优化的时候会去想到, 并可能有用的想法, 不知道你没有其他类似的方法, 大家可以一起讨论讨论:)  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-11 00:03 | 罗宾李
如果是java,那优化的余地不大。但是如果是c++,那不同的实现效果会差别很大,c++里面有很多技巧是java里面不能用的,比如创建私有堆,重载资源分配等等,当然,最重要的是使用了合适的东西去做恰当的事情。
看了你的文章有一个地方我不能不指出,就是你说用一个map来保存对象的长度这个做法我认为是很不科学的,首先map的查找时间是O(logN)级别的,反复查找总是有开销的,其次既然你已经用对象指针做key,那为何不把长度做为对象的一个属性,那样更新和获取都是O(1)的,当对象数量非常巨大时,你会知道这个差别有多大。一般map用在正好相反的情况,就是根据长度找对象,这个时候用map是很不错呃选择,如果长度有重复,可以考虑multimap。
根据我经历过的几个c++的优化项目,最终的瓶颈都是在如何正确的cache数据上。  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-11 00:58 | SmartPtr
@罗宾李
1. 当然,对于特定于语言的优化,C++比Java应该要好一些, 毕竟C++是一个更底层,可控性更强的语言。 但是对于workflow上的优化, 应该是语言无关的。我们所做的性能的提升,大部分是靠对workflow的优化实现的。

2. 关于map使用, 谢谢你的评论, 你说的很对。 这个例子为了简化,我没有给出足够的context. 我补充一些吧:
1) 该对象是一个API, 一个第三方库,我们没有权限去修改
2) 假设这个对象是一条样条曲线, 该第三方库没有在该对象中加入一个长度属性,而是在每次需要时去计算,从数学角度,我想应该也有其道理。(这样我就能保证每次取到的都是最新的)
重要的是,我们都认同cache是性能优化的利器, 的确,设计好的cache数据结构的确很重要,当然,这都是和特定需求紧密结合在一起的。

  回复  更多评论
  
# re: 我对软件优化的一些想法[未登录]
2007-08-13 09:40 | 梦在天涯
很好,就是有点抽象哦,哈哈!  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-13 10:05 | zenith
还好,我们做的项目都不是太大,重构一次也不算很难,呵呵。。。  回复  更多评论
  
# re: 我对软件优化的一些想法
2007-08-16 12:51 | houdy
对于算法的好坏,只有当N相当大的时候,效果才很明显,对于一般的情况从O(N^2)优化到O(NlogN),效果并不是很明显.
但是LZ说得这几种情况,有时候效果却很明显.其中的cache的思想,几乎应用到计算机领域的各个方面,例如对于数据存储,CPU缓存,内存,硬盘,网络硬盘,不就是用速度快的设备去cache数据慢的设备么?
  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理