本章讨论程序性能调整问题,性能问题可以从两个层面上考虑:策略上和技术上。本章要解决的是策略层面上的性能问题:
性能概述
性能和代码调整
请从以下方面来思考效率问题:
- 程序需求;
- 程序的设计;
- 类和子程序的设计;
- 程序同操作系统的交互;
- 代码编译;
- 硬件;
- 代码调整。
代码调整简介
Pareto法则
Pareto法则也就是总所周知的80/20法则,它讲述的是你可以用20%的努力取得80%的成效。
一些无稽之谈
- 在高级语言中,减少代码的行数就可以提升所生成的机器代码的运行速度,或是减少其资源占用——错误!
- 特定运算可能比其他的快,代码规模也较小——错误!
- 应当随时随地进行优化——错误!
- 几乎不可能在程序所有的功能都运转之前去顶出程序的性能瓶颈;
- 在极少情况下,程序员能正确确定出程序的瓶颈;
- 在最初的开发阶段中,程序员老是把目光集中在优化上面会干扰自己对其他程序目标的判断和理解,让自己沉浸在那些最终并没有为用户提供多大价值的算法分析和晦涩的讨论中,把对正确性、信息隐藏、可读性等的考虑放到了第二位。
- 程序的运行速度同其正确性同等重要——错误!
何时调整代码
在程序已经完成并正确之后,再去检查系统的性能。如果程序运行迟钝,那么再设法让它更快更小。除非你对需要完成的工作一清二楚,否则绝对不要对程序做优化。
蜜糖和哥斯拉
常见低效率之源
- 输入/输出操作;
- 分页;
- 系统调用;
- 编写字节的服务程序;
- 避免进入系统;
- 尝试同系统软件商沟通。
- 解释型语言;
- 错误。
性能测量
性能测量应当精确
应当用分配给程序的CPU时钟来计算,而不是日期时钟。
反复调整
几乎不可能一次就能够实现代码获得很大的性能改进,应该通过反复调整,将多种方法结合起来,反复尝试,直到发现有用的方法。
代码调整方法总结
如果还对代码调整能否有助于提高某个程序的性能心存疑虑,按照以下步骤去做把:
- 用设计良好的代码来开发软件,从而使程序易于理解和修改;
- 如果程序性能很差;
a. 保存代码的可运行版本,这样你才能回到最近的已知正常状态;
b. 对系统进行分析测量,找出热点;
c. 判断性能拙劣是否源于设计、数据类型或算法上的缺陷,确定是否应该做代码调整,如果不是,请跳回第一步;
d. 对步骤c中所确定的瓶颈代码进行调整;
e. 每次调整后都对性能提升进行测量;
f. 如果调整没有改进代码的性能,就恢复到步骤a保存的代码; - 重复步骤2。
核对表:代码调整策略
程序整体性能
- [ ] 你是否考虑通过修改需求来提高性能?
- [ ] 你是否考虑通过修改程序的设计来提高性能?
- [ ] 你是否考虑通过修改类的设计来提高性能?
- [ ] 你是否考虑过减少程序同操作系统的交互从而提高性能?
- [ ] 你是否考虑过避免I/O操作以提高性能?
- [ ] 你是否考虑过使用编译型语言来替代解释型语言以提高性能?
- [ ] 是否考虑过使用不同的硬件来提高性能?
- [ ] 是否仅仅将代码调整看作是解决问题的最后一招?
代码调整方法
- [ ] 在开始调整代码之前,程序是完全正确的吗?
- [ ] 在调整之前是否测量过性能瓶颈在什么地方?
- [ ] 是否记录了每一次修改所产生的效果?
- [ ] 如果没有带来预期的性能提高,你是否放弃了所做的代码调整策略?
- [ ] 你是否对每一个性能瓶颈进行不止一次的修改尝试——也就是说,你是在反复进行代码调整么?
要点
- 性能只是软件整体质量的一个方面,通常不是最重要的。精细的代码调整也只是实现整体性能的一种方法,通常也不是决定性的。相对于代码本身的效率而言,程序的架构、设计细节异界数据结构和算法的选择对程序的运行速度和资源占用的影响通常会更大;
- 定量测量是实现性能最优化的关键。定量测量需要找出能真正决定程序性能的部分,在修改之后,应当通过重复测量来明确修改时提高还是降低了软件的性能;
- 绝大多数的程序都有那么一小部分代码耗费了绝大部分的运行时间。如果没有测量,你不会知道是哪一部分代码;
- 代码调整需要反复尝试,这样才能获得理性的性能提高;
- 为性能优化工作做好准备的最佳方式就是在最初阶段编写清晰的代码,从而使代码在后续工作中易于理解和修改。