程序性能优化概述

内容纲要

为什么写这篇文章

本周针对一个响应缓慢达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开发之道》

Leave a Comment

您的电子邮箱地址不会被公开。 必填项已用*标注

close
arrow_upward