警惕程序优化的七大陷阱

优化,仅从字面上就给人一种美好的感觉。没错,优化是一个好东西。通过优化,我们可以减少程序占用的内存,可以缩短计算耗费的时间,可以处理以前处理不完,处理不了的数据。但是,俗话说得好,every rose has its thorn,围绕着优化,有许多陷阱,需要小心避开。下面结合个人经验,总结一下程序优化的七大陷阱。

一、优化够用的程序。经常会见到有人在论坛上抱怨说,前任程序员写的代码虽然凑合能用,但是左看右看怎么看都觉得碍眼,觉得这里不够优化,那里还能改进,想要刷刷刷删掉重写。实际上,大量重写可用的代码从来不是一个轻松的工作,决定重写和优化之前,一定要慎之又慎。毋庸置疑,重写代码可以让程序的结构更好,可以提高性能,但是同时也需要耗费大量人月,需要承担破坏程序可用性的风险。回想多年之前维护的那个大型系统,它从代码风格到算法实现都让我不断地摇头叹息,每次改动起来都不得不捏着鼻子。但是我拿它没有办法,因为事实证明,它能够胜任自己的工作。直到有一天,领导叫住我说,别在这坨东西上修修补补了,你需要做的是全新的一套,放手去干吧,我给你充足的时间。这时候,我知道自己的机会来了,是时候翻开新篇章了。

二、优化老化的程序。这是第一种陷阱的反面。做这种优化就像是给一个老化的桑塔纳换上兰博基尼的发动机,得不偿失。软件虽然不像硬件那样,有着固有的物理生命周期,但是也有生老病死。随着时间的推移,软件需要不断地升级换代。如果软件的结构不好,或者主刀手没有高超的技艺,那么过了一段时日之后,程序就会得像魔兽争霸里面的憎恶一样,一眼看上去就是那么恐怖吓人,恶心至极。优化这样的程序,不仅工程量大,耗时长,而且维护极为困难。在另外一些情况下,程序本身内部仍然很健康,但已明显跟不上外部条件的变化,如需求的提高,软硬件环境的换代等。此时,也不要再纠结是不是还要在继续老程序上修修补补了。要知道,想养个恐龙当宠物,得从孵化恐龙蛋开始,科莫多喂得再大也还是蜥蜴。

三、过早地优化程序。.很多事情,即使很有必要做,也需要找到合适的时机,程序优化也是一样。一般来说,相对于过晚优化,过早优化的情况发生地更为普遍。因为随着时间的推移,程序的缺陷会暴露得越来越清晰。只要反馈机制不是过于薄弱,公司结构不是过于尾大不掉,开发者的神经不是过于大条,那么他会及时地收到警报。之所以强调不要过早优化,是因为在程序开发运行的早期,相比于优化,有很多更重要的事情要处理。例如很多时候,功能实现比程序优化更为重要,因为新增功能是一个零到一的阶跃,而程序优化是从一到一百的渐变。如果在系统还没有完成的时候,就搁置其他更重要的事情,心急火燎地开始优化,最后很有可能被证明是在浪费时间,甚至会适得其反。同时应该注意到,对系统特新和应用特点的理解,是一个积累的过程,需要一定时间的理解和分析。只有对系统理解充分了,把测试数据掌握全面了,结果分析透彻了,才能找到影响性能的关键因素,才能直指问题本质。

四、设立过于乐观的优化目标。我不是一个悲观主义者,但是几十载的经历告诉我,从来没有什么好事能不需要努力争取,而莫名其妙从天上掉下来。天上掉下来的不是馅饼,也不是林妹妹,而是一坨一坨的烦心事。因此,对每件事,我都保持谨慎的乐观,对程序优化也是如此。凭着这种观念,我最近就与同事进行了一番争吵。那时我们对一个高速缓存系统的设计进行讨论。他说希望能把系统做得的高效,高性能,并且非常通用。我一听,立即产生了警觉,反诘道,凭什么它的性能比页高速缓存高,同时又能和页高速缓存一样通用?难道是说页高速缓存实现得太烂,不然怎么会那么轻而易举被我们超越?经过一番激烈的争论,我们才达成了共识,认清了修改接口语义的必要性,也就意味着应用需要为性能提升付出代价,它们要忍受一致性语义的放松。这时,我才放下心来,因为它符合我中庸的观念,终于没有设立过于完美的预期目标。理想是丰满的,现实是骨感的。在骨感的现实面前,只有设立可行的优化目标,才不会在谜底揭晓的那一刻给自己的信心以沉重的一击。

五、在错误的层次上优化。这里层次的含义是什么呢?我们都知道软件开发的流程首先是进行需求分析,然后设计架构,确定数据结构,选择算法,最后是编码实现。这是一个阶段一个阶段,步步推进的过程,也对应了可以进行优化的各个层次。其中,可以产生最大优化效果的是对应用需求进行深入挖掘。君不见一些重大优化手段的提出就是因为发现了应用中可以利用的特殊性质。利用这些性能,可以优化系统结构的设计,进而决定数据结构与算法的选择,最后影响到编码细节。然而,很多人有意无意忽视了这一点。相反,一些具体实现上的细节,如编程语言、编译器、硬件结构的特性等,造成的细微性能差异却被众多的书籍长篇累牍地谈论。许多程序员也因知晓这些细节而深感自豪。更有甚者,一些IT企业在面试时经常拿出些不知道那个角落里翻出来的老古董作为考察应聘者的题目。殊不知,过度地抠挖细节,实际上是拣了芝麻丢了西瓜,最后发现这些细节上的优化,不仅没有可移植性,而且其空间会不断地被编译器等底层软硬件的优化蚕食,最后只是沦为一种智力游戏而已。因此,这里需要大声疾呼,过度抠挖细节的习惯是上古时代遗留下来的糟粕,需要及时摒弃。对这种行为,早就有人给予了批评,但一般主要强调的是算法的重要性,也即算法如果太烂,细节处理得再好,性能也上不去。不过,经过这么多年的积累,基础算法已经发展得极为完备了,需要用到的常用算法,基本上都能找到前人的成果,可继续挖掘的空间并不是太大。反倒是算法之上的系统架构与应用需求分析,则越来越彰显出其重要性。可以确信的是,在这方面有足够广阔的空间供各领域的程序员大做文章,施展抱负。

六、优化错误的代码片段。说得老套一点,就是抓住主要矛盾,忽略次要矛盾,也可以表述成哪里都能见到它的“二八原理”,即百分之二十的代码消耗了八分之八十的时间,只有优化这一段代码,才能取得明显效果。这虽然是老生常谈,但是总有人在这上面耗费青春,纠结在一些完全不会造成性能瓶颈的地方,所以这里还是强调一下。

七、过度重复前人的工作。牛顿说,他是站在巨人肩膀上摘苹果的。我说,与从前的巨人相比,我们只是一帮孩纸。说,只要想得到,就能做得到。我说,即使我能想得到,可能也做不到,但是这个世界上肯定有人已经做到了,不然就是根本不可能有人能做到。好了,不掰扯了。我想说的是,对于一个新问题,只要应用场景不是特殊,不是那么难以描述,不是没有办法敲入到搜索框中,那么一定能找到前人在这方面的相关工作。很多时候,我等芸芸众生所做的事情,不过是把前人总结的经验再经历一遍,把前人发现的知识再学习一遍,把前人的一般性成果在实际工程中再应用一遍。所以,动手优化程序之前还是要多找找论文,多翻翻TAOCP,多搜搜开源软件,看看能不能借鉴前人的工作。当然,也不要期望前人能帮我们完成所有的事情,他们不可能在昨天就煮熟我们今天吃的米饭,但是米饭究竟要怎么煮熟煮香煮好,肯定已经被他们研究得透彻见底了。

在软件开发中,设计、实现、测试和优化是几大主题。其中设计要全面、系统,实现要现实、实用,测试要细致、严格,而优化时则需要谨慎小心。

你可能感兴趣的:(警惕程序优化的七大陷阱)