软件性能瓶颈分析方法及优化影响软件应用性能的因素有很多,下面简单介绍下其中几种影响因素及分析方法。
一、性能瓶颈分析1、内存分析内存的使用情况是系统性能中重要的因素之一,频繁的页交换及内存泄露都会影响到系统的性能(这里主要以Windows系统为主)。
内存分析用于判断系统有无遇到内存瓶颈,是否需要通过增加内存等手段提高系统性能表现。
(1)、查看Memory\Available Mbytes指标在对系统进行操作系统级别的内存分析时,首先需要通过该指标(Available Mbytes:Windows系统自带计数器的一个计数值)建立一个初步的印象,了解性能测试过程中系统是否仍然有足够的内存可用。
如果该指标比较小,系统可能存在内存不足方便的问题,这时需要继续依据具体问题进行下一步分析。
(2)、注意Pages/sec、Pages Read/sec和Page Faults/sec的值操作系统经常会利用磁盘交换方式提高系统的可用内存量或内存使用效率。
Windows和Unix操作系统都提供了类似的方法来支持磁盘交换计数,而这三个指标直接反应了操作系统进行磁盘交换的频度。
如果Pages/sec的计数持续高于几百,很可能有内存方面的问题产生,但Pages/sec的值很大不一定表明内存有问题,而可能是运行使用内存映射文件的程序所致。
Page Faults/sec值表示每秒发生的页面失效次数,页面失效次数越多,说明操作系统向内存读取的次数越多。
Pages Read/sec的计数值阈值为5,如果计数值超过5,则可以判断存在内存方面的问题。
(3)、根据Physical Disk计数器的值分析性能瓶颈对Physical Disk计数器的分析包括对Pages Read/sec和%DiskTime及Average Disk Queue Length的分析。
如果Pages Read/sec的值很低,同时%DiskTime和Average Disk Queue Length的值很高,则可能是磁盘瓶颈;但如果队列长度增加的同时Pages Read/sec并未降低,则是由于内存不足。
2、处理器分析处理器(CPU)也可能是系统的瓶颈,下面是针对处理器进行分析的步骤:(1)、查看System\%Total Processor Time性能计数器的计数值该计数值用于体现服务器整体的处理器利用率;对于多处理器系统而言,该计数值体现的是所有CPU的平均利用率。
如果该数值持续超过90%,则说明整个系统面临着处理器方面的瓶颈,需要通过增加处理器来提高性能。
注意事项:由于操作系统本身的特性,在某些多CPU系统中,该数据本身并不大,但如果CPU之间负载状况极不均衡,也应该视作系统产生了处理器方面的瓶颈。
(2)、查看每个CPU的Processor\%Processor Time、Processor\%User Time和Processor\%Privileged TimeProcessor\%User Time是指系统非核心操作消耗的CPU时间;如果该值较大,可以考虑是否能通过算法优化等方法降低该值。
如果该服务器是数据库服务器,Processor\%User Time值较大的原因很可能是数据库的排序或者函数函数操作消耗了过多的CPU时间,此时可考虑对数据库系统进行优化。
(3)、研究分析系统处理器瓶颈查看System\Processor Queue Length计数器的值;当该计数器的值大于CPU数量总数+1时,说明产生了处理器阻塞。
在处理器的%Process Time值很高时一般都伴随着处理器阻塞,但产生处理器阻塞时,Processor\%Process Time计数器的值并不一定很大,此时就需要查找处理器阻塞的原因。
%DPC Time的计数值越低越好。
在多处理器系统中,如果该值大于50%并且Processor\%Processor Time值非常高,则考虑加一个网卡来提高性能。
3、磁盘I/O分析方法磁盘I/O也是影响系统性能的一个关键因素。
如果所分析的计数器指标来源于数据库服务器、文件服务器或流媒体服务器,磁盘I/O更容易成为瓶颈。
磁盘I/O的分析方法如下:(1)、计算每个磁盘的I/O数每个磁盘的I/O数可以用来与磁盘的I/O能力进行对比,如果经过计算得到的每个磁盘I/O数超过了磁盘标称的I/O能力,则说明确实存在磁盘的性能瓶颈。
下表给出了每个磁盘I/O的计算方法:PS:各种不同的RAID方式,其每个磁盘I/O数的计算方法都不同。
(2)、与Processor\Privileged Time合并进行分析如果在Physical Disk计数器中,只有%Disk Time值较大,其他值都比较适中,则硬盘可能会是瓶颈;若几个值都比较大,且数值持续超过60%,则可能是内存泄漏。
(3)、根据Disk sec/Transfer进行分析一般而言,定义Transfer数值小于15位优秀,介于15~30之间为良好,30~60毫秒之间为可以接受,超过60毫秒则需要考虑更换硬盘或硬盘的RAIN方式。
4、进程分析方法(1)、查看进程的%Processor Time值每个进程的%Processor Time值反映出进程所消耗的处理器时间。
将不同进程所消耗的处理器时间进行对比,可以容易的看出具体哪个进程在性能测试过程中消耗了最多的处理器时间,从而可以据此针对应用进行优化。
(2)、查看每个进程产生的页面失效可以用每个进程产生的页面失效和系统的页面失效来判断哪个进程产生了最多的页面失效;该进程要么是需要大量内存的进程,要么是非常活跃的进程,可对其重点分析。
进程产生的页面失效:可以通过Process\Page Failures/sec计数器获得;系统的页面失效:可以通过Memory\Page Failures/sec计数器获得;(3)、了解进程的Process\Private BytesProcess\Private Bytes是指进程所分配的无法与其他进程共享的当前字节数量;其主要用来判断进程在性能测试过程中有无内存泄漏。
5、网络分析方法随着应用对数据传输量的增长,网络有时也会成为系统性能的瓶颈;一般在企业中,网络一般都是由专门的人员进行管理的(俗称运维、网管)。
如果在测试过程中怀疑是网络原因造成的系统瓶颈,可以要求网络管理人员来协助进行网络方面的监视检测;其中Network Interface\Bytes Total/sec为比较重要的属性;Network Interface\Bytes Total/sec:发送和接受字节的速率;可以通过该值判断网络连接速度是否是瓶颈,具体操作方法是:用该计数器的值与目前网络带宽进行比较。
二、性能优化1、性能优化的三个方面(1)、降低响应时间(2)、提高系统吞吐量(3)、提高服务的可用性三者的关系:在某些场景下互相矛盾,不可兼得2、性能优化面临的挑战(1)、日益增长的用户数量(2)、越来越复杂的业务(3)、急剧膨胀的数据3、性能优化的目标在保持和降低系统99%RT的前提下,不断提高系统吞吐量,提高流量高峰时期的服务可用性。
4、本文涉及的几种原则(1)、最小可用原则也称为快速接入原则,有两个关注点:①、快速接入,快速完成;②、实现核心功能可用;目标:通过降低开发测试周期,增加试错机会,快速接入而实现风险可控;注意:这并不意味着成本的降低,而需要为重构做好准备;相关阅读:在产品设计上有一个名词叫做MVP,即最小可行性产品,这一观点在《人人都是产品经理1.0纪念版》一书中有相关章节描述。
(2)、经济原则软件项目生命周期包括:预研、设计、开发、测试、运行、维护等阶段。
上面提到的最小可用原则主要运用在预研阶段,而经济原则既可以用在整个软件生命周期里,或只关注某一个或者几个阶段;例如:运行时经济原则需要考虑的系统成本包括单次请求的CPU、内存、网络、磁盘消耗等;设计阶段的经济原则要求避免过度设计;开发阶段的经济原则可能关注代码复用,工程师资源复用等。
(3)、代码复用原则该原则分两个层次:①、使用已有的解决方案或调用已存在的共享库(Shared Library),也称为方案复用;②、直接在现有的代码库中开发,也称之为共用代码库;方案复用原则出发点就是最大限度地利用手头已有的解决方案,即使这个方案并不好;方案的形式可以是共享库,也可以是已存在的服务。
优点:提高生产效率;类似:方案复用类似于微服务架构(Microservice Architecture),restful风格,设计出可重用性的组件或服务,通过分层组织各层组件来实现良好的架构。
共用代码库原则要求代码库中的所有功能编译时可见,新功能代码可以无边界的调用老代码;另外,原代码库已存在的各种运行、编译、测试、配置环境可复用。
优点:①、充分利用代码库中已有的基础设施,快速接入新业务;②、直接调用原代码中的基础功能,避免网络或进程间调用开销,性能更佳;类似:共用代码库和整体架构(Monolithic Architecture)很接近,它希望尽可能在一套代码库中开发,通过直接调用代码中的基础功能实现性能优化和快速迭代。
(4)、奥卡姆剃刀原则一般情况下,系统的代码量会随着功能的增加而变多,健壮性有时候也需要通过编写异常处理代码来实现,异常考虑越全面,异常处理的代码量就越大。
随着代码量的增大,引入BUG的概率也越大,系统也就越不健壮。
从另一个方面来说,异常流程处理代码也要考虑健壮性的问题,这就形成了无限循环。
奥卡姆剃刀原则要求:①、一个功能模块如非必要,就不要;②、一段代码如非必写,则不写;区别:最小可用原则主要运用于产品MVP阶段,奥卡姆剃刀原则主要指系统设计和代码编写两个方面,这是完全不同的两个概念;MVP包含系统设计和代码编写,但同时,系统设计和代码编写也可以发生在成熟系统的迭代阶段。
5、性能恶化模式性能优化的目标之一就是避免系统进入性能恶化模式;不同性能优化模式可能是避免同一种性能恶化模式;同一种性能优化模式可能在不同阶段避免不同的性能恶化模式;常见的性能恶化模式(1)、长请求拥塞恶化模式介绍:单次请求时延变长导致系统性能恶化甚至崩溃的模式;典型场景:复杂的业务场景依赖于多个服务,其中某个服务的响应时间变长,随之系统整体响应时间变长,进而出现CPU、内存、Swap报警;具体表现:被依赖服务可用性降低、大量RT变长导致线程堆积、内存使用增加,频繁GC,RT时间变得更长,最终导致服务彻底崩溃;表现方式:线程数变多导致县城之间CPU资源竞争,反过来进一步延长了单次请求时间;线程数增多及线程中缓存变大,内存消耗加剧,java语言的服务会频繁的full GC(垃圾回收),导致单次请求时间变得更长;内存使用变多,使操作系统内存不足,必须使用Swap(内存)交换,可能导致服务崩溃;恶化流程图如下:(2)、反复缓存恶化模式介绍:为降低响应时间,加缓存是种很有效的方式,缓存数据越多,命中率越高,ART就越快;典型场景:流量高峰冲击时,系统内存使用增多,出发了JVM进行full GC,进而导致大量缓存被释放,而大量请求又使得缓存被迅速填满,反复缓存导致频繁的full GC,频繁的full GC往往导致系统性能急剧恶化;原因:反复缓存所导致性能恶化的原因是无节制的使用缓存;指导原则:全局考虑,精细规划,确保系统完全缓存情况下系统仍然不会频繁full GC,严格控制缓存大小,甚至废除缓存;解决措施:线性的增加机器和提高机器的内存大小,可以显著减少系统崩溃的概率;恶化流程图如下:(3)、多次请求杠杆恶化模式介绍:客户端一次点击往往会出发多次服务端请求,每个服务端请求触发更多底层服务请求,请求层级越多,杠杆效应越大;典型场景:多次请求杠杆模式下运行的分布式系统,深层次的服务需处理大量请求,容易成为系统瓶颈;另外大量请求会给网络带来巨大压力,可能会成为系统彻底崩溃的导火索;表现方式:性能恶化和流量之间往往遵循指数曲线关系,且线性增加机器解决不了可用性问题;恶化流程图如下:6、性能优化模式(1)、水平分割模式动机:典型的服务端流程包含四个环节:接受请求、获取数据、处理数据、返回结果,大部分耗时长的服务发生在中间两个环节。