ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### 重构与性能(Performance) 译注:在我的接触经验中,performance—词被不同的人予以不同的解释和认知:效率、性能、效能。不同地区(例如台湾和大陆)的习惯用法亦不相同。本书一遇performance我便译为性能。effcient译为高效,effective译为有效。 关于重构,有一个常被提出的问题:它对程序的性能将造成怎样的影响?为了让软件易于理解,你常会做出一些使程序运行变慢的修改。这是个重要的问题。我并不赞成为了提高设计的纯洁性或把希望寄托于更快的硬件身上,而忽略了程序性能。己经有很多软件因为速度太慢而被用户拒绝,日益提高的机器速度亦只不过略微放宽了速度方面的限制而已。但是,换个角度说,虽然重构必然会使软件运行更慢,但它也使软件的性能优化更易进行。除了对性能有严格要求的实时(real time)系统,其他任何情况下「编写快速软件」的秘密就是:首先写出可调〔tunable)软件,然后调整它以求获得足够速度。 我看过三种「编写快速软件」的方法。其中最严格的是「时间预算法」(time budgeting),这通常只用于性能要求极高的实时系统。如果使用这种方法,分解你的设计时就要做好预算,给每个组件预先分配一定资源——包括时间和执行轨迹 (footprint)。每个组件绝对不能超出自己的预算,就算拥有「可在不同组件之间调度预配时间」的机制也不行。这种方法高度重视性能,对于心律调节器一类的系统是必须的,因为在这样的系统中迟来的数据就是错误的数据。但对其他类系统(例如我经常开发的企业信息系统)而言,如此追求高性能就有点过份了。 第二种方法是「持续关切法」( constant attention)。这种方法要求任何程序员在任何时间做任何事时,都要设法保持系统的高性能。这种方式很常见,感觉上很有吸引力,但通常不会起太大作用。任何修改如果是为了提高性能,通常会使程序难以维护,因而减缓开发速度。如果最终得到的软件的确更快了,那么这点损失尚有所值,可惜通常事与愿违,因为性能改善一旦被分散到程序各角落,每次改善都只不过是从「对程序行为的一个狭隘视角」出发而已。 关于性能,一件很有趣的事情是:如果你对大多数程序进行分析,你会发现它把大半时间都耗费在一小半代码身上。如果你一视同仁地优化所有代码,90%的优化工作都是白费劲儿,因为被你优化的代码有许多难得被执行起来。你花时间做优化是为了让程序运行更快,但如果因为缺乏对程序的清楚认识而花费时间,那些时间都是被浪费掉了。 第三种性能提升法系利用上述的“90%”统计数据。采用这种方法时,你以一种「良好的分解方式」(well-factored manner)来建造自己的程序,不对性能投以任何关切,直至进入性能优化阶段——那通常是在开发后期。一且进入该阶段,你再按照某个特定程序来调整程序性能。 在性能优化阶段中,你首先应该以一个量测工具监控程序的运行,让它告诉你程序中哪些地方大量消耗时间和空间。这样你就可以找出性能热点〔hot spot)所在的一 小段代码。然后你应该集中关切这些性能热点,并使用前述「持续关切法」中的优化手段来优化它们。由于你把注意力都集中在热点上,较少的工作量便可显现较好的成果。即便如此你还是必须保持谨慎。和重构一样,你应该小幅度进行修改。每走一步都需要编译、测试、再次量测。如果没能提高性能,就应该撤销此次修改。你应该继续这个「发现热点、去除热点」的过程,直到获得客户满意的性能为止。 关于这项技术,McConnel [McConnel]为我们提供了更多信息。 一个被良好分解(well-factored)的程序可从两方面帮助此种优化形式。首先,它让你有比较充裕的时间进行性能调整(performance tuning),因为有分解良好的代码在手,你就能够更快速地添加功能,也就有更多时间用在性能问题上(准确的量测则保证你把这些时间投资在恰当地点)。其次,面对分解良好的程序,你在进行性能分析时便有较细的粒度(granularity),于是量测工具把你带入范围较小的程序段落中,而性能的调整也比较容易些。由于代码更加清晰,因此你能够更好地理解自己的选择,更清楚哪种调整起关键作用。 我发现重构可以帮助我写出更快的软件。短程看来,重构的确会使软件变慢,但它使优化阶段中的软件性能调整更容易。最终我还是有赚头。