为什么要写这个课题?
性能优化,曾经是个比较高端的话题,能干这个活的人一定是团队中的大牛,但这些年来由无数的公司、无数的产品、无数的程序员做了各种各样的实践,已经成为一项比较成熟的技术课题,没那么神秘了,那为什么还要写它呢?
笔者希望通过自己在实践中积累的经验,把性能优化这件事用自己的体系梳理一遍,一来当做自己的学习笔记,自己回头多看看也有新的想法冒出来;二来希望有这方面需求的人能看到它,少走一些弯路,带来一些启发,搞定自己遇到的问题。
性能优化和Go语言有什么关系?
性能优化,严格意义上与编程语言有一定关系,但除了编程语言之外还有众多的考虑因素。那么这里为什么要写Go语言应用程序的性能优化呢,是因为笔者日常工作使用Go语言最多,近几年做过的大部分性能优化案例也是和Go语言相关的,因此从这个主题入手来聊聊性能优化这件事更有说服力。
当然,Go语言有自己独特的设计,就像Java程序员津津乐道的JVM调优一样,Go中也有很多独特的特性,针对这些特性确实有较多的方法论值得讨论。
性能优化的方法论
现代管理学之父彼得·杜拉克有一句名言:
If you can't measure it, you can't manage it.
虽然这句话说的是管理,但是放在性能优化上面依然是一针见血,转换成程序员的专属话术就是:如果你没办法衡量它,你就没办法优化它!
因此,性能优化最重要的事,不是埋头去看代码、去改代码,而是要衡量目前系统的状况,看看性能瓶颈在哪里,谋定而后动,知道问题在哪里,优化就成了水到渠成的事情。
笔者自己总结的一套方法论如下:

- 性能优化一般都是从性能数据的测量开始,一般来说我们肯定有一个业务目标,比如说希望在X台4U16G的机器上,系统QPS达到XXX,或者说整个系统QPS在XXX的时候,延迟 pct99 < X毫秒;
- 有了这个目标之后,我们就要根据压测情况来看,当前系统中的资源使用情况是否符合预期,一般比较典型的有两种:系统资源利用率比较低,代码写的不好,或者架构设计不合理,某项资源到达瓶颈性能无法提升系统资源利用率很高,已经没有足够的资源支撑更高的性能,这种情况就需要对代码进行进一步的分析和优化;
- 针对2中的第一种情况,我们要分析资源使用瓶颈在哪里,短板效应往往在这里体现得淋漓尽致,一般情况下解决了资源瓶颈,性能问题可能就已经不存在了;
- 针对2中的第二种情况,我们要去分析代码哪里写得不好,除了人肉review代码之外,还有众多的工具可以做到这一点(悄悄说一句,除了优化代码,加资源也可以解决问题,不过这体现不出我们的价值);
- 知道了资源瓶颈,或代码中的性能陷阱,我们就可以进行专门的优化,代码上的技巧虽然细节,但是属于整个过程中最容易掌握的部分,也是最容易产生收益的地方;
- 除了代码上的问题之外,还有一种比较隐蔽的问题,也容易被程序员忽略,即业务逻辑存在问题,做了很多的无用功,对其优化会产生意想不到的效果。
遇到性能问题,我们可以大体按照上述顺序做分析,往往没办法在一轮分析之后解决,需要多轮的分析,循环往复,直到性能满足要求为止(或者实在无法达到目标而放弃)。
三部曲导读
方法论中提到的整个性能优化的思路,每一步中都包含了大量的细节,我们不可能在这一篇文章中穷尽,所以后面还有三篇文章来更细节的聊聊它们。
性能指标篇,讲述一般情况下我们应该关注的指标,以及它背后的含义。
资源使用篇,讲述系统当中关键资源的使用,以及它们对性能的影响。
代码优化篇,讲述Go语言当中一些常用的性能优化技巧,以及部分系统设计上的优化。
如果大家感兴趣,在三部曲之外,笔者也可以分享一些自己曾经遇到过比较典型的性能优化案例,结合三部曲当中提及的方法论,来详细的讲述如何做一次有效的性能优化。
这个系列不包含什么内容?
这个系列文章讲了应用程序优化的一般技术,但性能问题本身就是一个非常复杂的课题,除了常见的消除资源瓶颈、调整代码逻辑、优化底层库和工具链,还有一些更复杂的技术,比如网络架构优化、底层硬件加速、应用整体架构优化等等,这些内容的复杂度比较高,如果有读者感兴趣可以留言,我们可以另外开专栏分享给大家。