为什么写这篇文章
本周针对一个响应缓慢达30秒的生产API接口,优化到1s的响应时间,故总结经验和优化步骤清单,方便后续直接翻阅检查。
优化对象
- 响应时间
- 吞吐量
程序性能表现方面
- 执行速度:程序的反应是否迅速,响应时间是否足够短。
- 内存分配:内存分配是否合理,是否过多地消耗内存或者存在泄漏。
- 启动时间:程序从运行到可以正常处理业务需要花费多长时间。
- 负载承受能力:当系统压力上升时,系统的执行速度和响应时间的上升曲线是否平缓。
程序性能的参考指标
- 执行时间:一段代码从开始运行到运行结束所使用的时间。
- CPU时间:函数或者线程占用CPU的时间。
- 内存分配:程序在运行时占用的内存空间。
- 磁盘吞吐量:描述I/O的使用情况。
- 网络吞吐量:描述网络的使用情况。
- 响应时间:系统对某用户行为或者事件做出响应的时间。响应时间越短,性能越好。
根据木桶原理,系统的最终性能取决于系统中性能表现最差的组件。因此,为了提升系统的整体性能,必须对系统中表现最差的组件进行优化,而不是对系统中表现良好的组件进行优化。
最有可能成为系统瓶颈的计算资源
- 磁盘I/O:由于磁盘I/O读写的速度比内存慢很多,程序在运行过程中,如果需要等待磁盘I/O完成,那么低效的I/O操作会拖累整个系统。
- 网络操作:对网络数据进行读写的情况与磁盘I/O类似,由于网络环境的不确定性,尤其是对互联网上数据的读写,网络操作的速度可能比本地磁盘I/O更慢,因此,如不加特殊处理,也极可能成为系统瓶颈。
- CPU:对计算资源要求较高的应用,由于其长时间、不间断地大量占用CPU资源,那么对CPU的争夺将导致性能问题。例如,科学计算、3D渲染等对CPU需求量大的应用便是如此。
- 异常:对Java应用来说,异常的捕获和处理是非常消耗资源的。如果程序高频率地进行异常处理,则整体性能便会有明显下降。
- 数据库:大部分应用程序都离不开数据库,而海量数据的读写操作往往是相当费时的。应用程序需要等待数据库操作完成并返回结果,那么缓慢的同步操作将成为系统瓶颈。
- 锁竞争:对高并发程序来说,如果存在激烈的锁竞争,对性能无疑是极大的打击。锁竞争将会明显增加线程上下文切换的开销,而且这些开销都是与应用需求无关的系统开销,白白占用宝贵的CPU资源,却不带来任何好处。
- 内存:一般来说,只要应用程序设计合理,内存在读写速度上不太可能成为性能瓶颈。除非应用程序进行了高频率的内存交换和扫描,但这种情况比较少见。内存制约系统性能最有可能出现的情况是内存容量不足。与磁盘相比,内存的容量似乎小得可怜,这意味着应用软件只能尽可能将常用的核心数据读入内存,这在一定程度上降低了系统性能。
Amdahl定律
Amdahl定律:定义了串行系统并行化后的加速比的计算公式和理论上限。
加速比定义:加速比=优化前系统耗时/优化后系统耗时
加速比越高,表明优化效果越明显。
Amdahl定律给出了加速比与系统并行度和处理器数量的关系。
设加速比为Speedup,系统内必须串行化的程序比重为F,CPU处理器的数量为N,则有
Speedup \le \frac{1}{F + \frac{1-F}{N} }
为了提高系统的速度,仅增加CPU处理器的数量并不一定能起到有效的作用。需要从根本上修改程序的串行行为,提高系统内可并行化的模块比重,在此基础上合理增加并行处理器的数量,才能以最小的投入得到最大的加速比。
注意:根据Amdahl定律,使用多核CPU对系统进行优化,优化的效果取决于CPU的数量及系统中串行化程序的比重。CPU数量越多,串行化比重越低,则优化效果越好。仅提高CPU数量而不降低程序的串行化比重,则无法提高系统性能。
性能调优的层次
-
设计调优:设计调优处于所有调优手段的上层,它往往需要在软件开发之前进行。
设计优化的一大显著特点是,它可以规避某一个组件的性能问题,而非改良该组件的实现。
设计优化直接决定了系统的整体品质。如果在设计层考虑不周,留下太多问题隐患,那么这些“质”上的问题,也许无法再通过代码层的优化进行弥补。
-
代码调优:代码调优是在软件开发过程中或者在软件开发完成后,软件维护过程中进行的对程序代码的改进和优化。代码优化涉及诸多编码技巧,需要开发人员熟悉相关语言的API,并在合适的场景中正确使用相关API或类库。同时,对算法和数据结构的灵活使用,也是代码优化的重要内容。
-
JVM调优:对JVM虚拟机进行优化也能在一定程度上提升Java程序的性能。JVM调优通常可以在软件开发后期进行,如在软件开发完成或者在软件开发的某一里程碑阶段进行。
要进行JVM层面的调优,需要开发人员对JVM的运行原理和基本内存结构有一定了解,例如堆内存的结构、GC的种类等,然后依据应用程序的特点,设置合理的JVM启动参数。
-
数据库调优:
对数据库的调优可以分为以下3个部分:·在应用层对SQL语句进行优化;·对数据库进行优化;·对数据库软件进行优化。
-
操作系统调优:不同类型的操作系统,调优的手段和参数可能会有所不同。
优化的一般步骤
参考书目
- 《Java程序性能优化实战》
- 《Java Web开发之道》