# 性能优化原则和方法

作为一个程序员，性能优化是常有的事情，不管是桌面应用还是web应用，不管是前端还是后端，不管是单点应用还是分布式系统。本文从以下几个方面来思考这个问题：性能优化的一般性原则，性能优化的层次，性能优化的通用方法。

### 一、一般性原则

#### 依据数据而不是凭空想象

这是性能优化的第一原则，当我们怀疑性能有问题的时候，应该通过测试、日志、profillig来分析出哪里有问题，有的放矢，而不是凭感觉、撞运气。一个系统有了性能问题，瓶颈有可能是CPU，有可能是内存，有可能是IO（磁盘IO，网络IO）等等

#### 忌过早优化

#### 忌过度优化

#### 深入理解业务代码

#### 性能优化是持久战

#### 选择合适的衡量指标、测试用例、测试环境

### 二、性能优化的层次

> 按照我的理解可以分为需求阶段，设计阶段，实现阶段；越上层的阶段优化效果越明显，同时也更需要对业务、需求的深入理解。

#### 需求阶段

> 不战而屈人之兵，善之善者也

　　程序员的需求可能来自PM、UI的业务需求（或者说是功能性需求），也可能来自Team Leader的需求。当我们拿到一个需求的时候，首先需要的是思考、讨论需求的合理性，而不是立刻去设计、去编码。

　　需求是为了解决某个问题，问题是本质，需求是解决问题的手段。那么需求是否能否真正的解决问题，程序员也得自己去思考，产品经理（特别是知道一点技术的产品经理）的某个需求可能只是某个问题的解决方案，他认为这个方法可以解决他的问题，于是把解决方案当成了需求，而不是真正的问题。

　　需求讨论的前提对业务的深入了解，如果不了解业务，根本没法讨论。即使需求已经实现了，当我们发现有性能问题的时候，首先也可以从需求出发。

　　需求分析对性能优化有什么帮助呢，第一，为了达到同样的目的，解决同样问题，也许可以有性能更优（消耗更小）的办法。这种优化是无损的，即不改变需求本质的同时，又能达到性能优化的效果；第二种情况，有损的优化，即在不明显影响用户的体验，稍微修改需求、放宽条件，就能大大解决性能问题。PM退步一小步，程序前进一大步。

　　需求讨论也有助于设计时更具扩展性，应对未来的需求变化，这里按下不表。

#### 设计阶段

　　高手都是花80%时间思考，20%时间实现；新手写起代码来很快，但后面是无穷无尽的修bug

　　设计的概念很宽泛，包括架构设计、技术选型、接口设计等等。架构设计约束了系统的扩展、技术选型决定了代码实现。编程语言、框架都是工具，不同的系统、业务需要选择适当的工具集。如果设计的时候做的不够好，那么后面就很难优化，甚至需要推到重来。

#### 实现阶段

　　实现是把功能翻译成代码的过程，这个层面的优化，主要是针对一个调用流程，一个函数，一段代码的优化。各种profile工具也主要是在这个阶段生效。除了静态的代码的优化，还有编译时优化，运行时优化。后二者要求就很高了，程序员可控性较弱。

&#x20;　　代码层面，造成性能瓶颈的原因通常是高频调用的函数、或者单次消耗非常高的函数、或者二者的结合。

　　下面介绍针对设计阶段与实现阶段的优化手段。

### 三、一般性方法

#### 缓存

&#x20;       缓存的本质是加速访问，访问的数据要么是其他数据的副本 -- 让数据离用户更近；要么是之前的计算结果 -- 避免重复计算。缓存需要用空间换时间，在缓存空间有限的情况下，需要优秀的置换换算来保证缓存有较高的命中率。

**缓存类型**

* 文件缓存
* 数据缓存
* 计算结果缓存

#### 并发

CDN缓存、多节点、http2.0

#### 惰性

讲计算、加载推迟到需要的时候。如图片懒加载、路由懒加载等

#### 批量、合并

#### 更高效实现

#### 缩小解空间

### 四、总结

![](https://2925742798-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lfbm7rCfl1blCD7FH_h%2F-M_dVQFCDJqAMXVkHahV%2F-M_dVvYuvkjeOOSXbeZh%2F%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E5%8E%9F%E5%88%99.png?alt=media\&token=2b5d0541-dc96-4cf2-a618-7de607e334f8)

参考：

<https://www.cnblogs.com/xybaby/p/9055734.html>

<https://wetest.qq.com/lab/view/316.html>
