可以在两个层面上考虑性能问题:策略上和技术上 。 本章要讨论的策略层面上的性能问题:什么是性能 它的重要性 以及提高性能的一般性方法。

性能概述

代码调整只是提高程序性能的一种方法 除此之外 你还能找到提高性能的其他方法。相对于代码质量 用户更关心的是程序的外在特性 只有在性能影响到了用户工作的时候 相对于纯粹的性能,用户更为重视的是程序的处理能力。性能同代码速度之间存在很松散的联系。 如果只是关注代码的运行速度 你的工作就会顾此失彼。过分强调速度 程序的整体性能(表现)常常不升反降。

以下几个方面思考效率问题

  • 程序需求 在处理性能问题之前 想清楚是的确在解决一个确实需要解决的问题
  • 程序的设计 为单个的子系统的性能设置目标 可以使最终性能可预测 目标越明确 子系统越可能满足。可能有一些目标无法直接提高效率 从长远来看能促进效率提升
  • 类和子程序的设计 合适的数据性能和算法 比如快速排序 替代冒泡
  • 程序同操作系统的交互 性能差可能是操作系统过于低效
  • 代码编译 编译器
  • 硬件 最经济最有效升级硬件

    代码调整 并不是最有效的—》修改程序设计 改善算法更有效 。也不是最方便的—》硬件。 也不是成本最低的—》初期手工调整过多 后期难以维护。

    受到青睐的原因:调整几行代码就可以带来巨大的性能提升 可以证明你很酷

    代码调整简介

    Pareto法则

    80/20法则 可以用20%的努力取得80%的成效。 研究表明 程序的20%的子程序耗费了80%的执行时间。不要过分追求完美 越是追求完美 越是有可能完不成任务。 程序员首要是应该实现程序所需要的所有功能,然后再十程序趋于完美 这个时候需要精益求精的地方是很少的。

错误说法

在高级语言中 减少代码行数就能提高所生成的机器码运行速度 或者是减少资源占用——错误! 抛开最简洁的代码所具备的美感不谈 行数和运行速度以及资源没有必然联系。

  1. for(let i=0;i<5;i++){
  2. a[i]=i
  3. }
  4. a[0]=0
  5. a[1]=1
  6. a[2]=2
  7. a[3]=3
  8. a[4]=4

特定的运算可能比其他的快 代码规模也较小 “可能” 不准确 应该实际测量 环境 设备 编译器等
应当随时随地优化 —- 错误 。 在极少情况 能正确判断程序瓶颈。 所有功能运行之前 几乎不可能确定瓶颈。 顾此失彼 早期开发阶段 过早考虑优化 把正确性 可读性放第二位是不合适的。
程序的运行速度与正确性同等重要 —- 错误 无法正确运行的前提不可能要求更快或者更小。

何时调整代码

应当把程序编写正确 模块化 更易于修改 让后期维护更容易。在程序完成并正确之后 再去检查系统的性能 设法让它更快更小。

蜜糖和哥斯拉

某些代码运行部分就像蜜糖一样黏糊糊 体积像哥斯拉。 目标就是优化 让运行起来快如闪电。

常见的低效率之源

不必要的输入输出 io操作 可以访问内存就不要访问数据库 跨越网络访问 磁盘操作等

  1. //导致较多的缺页中断
  2. for(column=0;row<MAX_COLUMN;column++){
  3. for(row=0;column<MAX_ROWS;row++){
  4. table[row][column] = blankelement()
  5. }
  6. }
  7. //优化后 导致较少的缺页中断
  8. for(row=0;row<MAX_ROWS;row++){
  9. for(column=0;column<MAX_COLUMN;column++){
  10. table[row][column] = blankelement()
  11. }
  12. }

性能测量

数组访问 循环条件判断花费很多时间
image.png
优化为指针后的
image.png
但是性能没有提升 编译器已经把数组访问改为指针实现。
性能优化要经过测量 否则想当然的优化结果可能是让代码变得更晦涩难懂。 如果认为没有必要通过测量来证实哪种更高效 也同样没必要为了牺牲代码可读性 来提高性能。

性能测量应当准确

性能测量工具 系统时钟和函数来记录运算操作所耗费的时间。

反复调整

确定性能瓶颈后 可能通过多次方法结合起来 反复尝试 直到发现来有用的方法。

代码调整方法总结

  1. 用设计良好的代码开发 使得程序便于理解与维护
  2. 如果程序性能很差
    1. 保持代码历史版本
    2. 对系统进行分析测量 找出热点
    3. 判断性能差原因是否因为 设计 数组类型或算法上的缺陷 确定是否应该对代码做出调整 如果不是 跳回第一步
    4. 对c 中所确定对瓶颈代码进行调整
    5. 每次调整后都对性能提升进行测量
    6. 如果调整没有改进性能 就恢复到a保存到版本 (通常而言 超过一半的调整尝试都只能稍微改善性能甚至还能性能恶化)

      要点

      性能只是 软件整体质量的一部分 通常不是最重要。 代码调整也只是实现整体性能的一种方法 也不是决定性 相对于代码本身的效率而言,程序的架构 细节设计以及数据结构和算法的选择对程序的运行速度和资源占用的影响会更大。
      定量测量是实现性能最优化的关键。 定量测量需要找出真正决定程序性能的部分。在修改之后 需要重复测量还明确修改是否有正向作用。
      绝大多数程序都是一小部分代码耗费了绝大部分的运行时间。
      代码调整需要反复尝试 。
      为性能优化做好准备的最佳方式就是在最初阶段编写清晰的代码,从而使代码在后续工作中易于理解和修改