`

读书笔记:《分布式JAVA应用 基础与实践》 第五章 性能调优(一)

阅读更多

5.1 寻找性能瓶颈

    通常性能瓶颈的表象是资源消耗过多、外部处理系统性能不足,或者资源消耗不多,但程序的响应速度却仍达不到要求。

    资源主要消耗在 CPU 、文件 IO 、网络 IO 、以及内存方面。

    外部处理的性能不够主要是调用其他系统的功能或数据库操作的响应速度不够。

    资源消耗不多,但程序的响应速度仍达不到要求的主要原因是程序代码运行效率不高,未充分使用资源或程序结构不合理。

    对于 JAVA 应用而言,寻找性能瓶颈的方法通常为首先分析资源的消耗,然后结合 JAVA 的一些工具来查找程序中资源消耗过多的代码。

5.1.1 CPU 消耗分析

    在 Linux 中, CPU 主要用于中断、内核及用户进程的任务处理,优先级为中断 > 内核 > 用户进程,在学习如何分析 CPU 消耗状况前,还有三个重要的概念要阐述。

1.       上下文切换

每个 CPU (或多核心 CPU 中的每核 CPU )同一时间只能执行一个线程, Linux 采用的是抢占式调度,即为每个线程分配一定的执行时间。线程执行时间到达而切换到其它线程时,就会触发上下文切换。上下文切换过多会造成内核占据较多的 CPU 使用,使得应用的响应速度下降。

2.       运行队列

每个 CPU 都维护了一个可运行的线程队列。通常建议控制在每个 CPU 核上的运行队列为 1-3 个。

3.       利用率

CPU 利用率为 CPU 在用户进程、内核、中断处理、 IO 等待以及空亲五个部分使用的百分比。建议用户进程和内核进程消耗的 CPU 比率在 65%-70%/30%-35% 左右。

 

linux , 可用 top pidstat 方式来查看进程中线程的 CPU 的消耗状况。

1.       top

CPU 行, us 表示用户进程处理所占的百分比 ;sy 表示内核进程所占的百分比 ; ni 表示被 nice 命令改变优先级的任务所占的百分比 ; id 表示 CPU 空闲时间所占的百分比 ; wa 表示为在执行的过程中等待 IO 所占的百分比 ; hi 表示为硬件中断所占的百分比 ; si 表示为软件中断所占的百分比

对于多个或多核的 CPU ,显示则会是多个 CPU 所占用百分比的总和,因此会出现 160%us 的现象,如需查看每个核的消耗情况,可在进入 top 视图后按 1 ,就会按核来显示消耗状况。

top 视图按 shift+h 后,可按线程查看 CPU 的消耗状况。

2.       pidstat

pidstat SYSSTAT 中的工具,如需使用,请先安装

pidstat 1 2 ,在 console 会每隔 1 秒输出目前活动进程的 CPU 消耗状况,共 2 次。

Pidstat –p [PID] –t 1 5 可查看某进程中线程的 CPU 消耗状况

 

CPU 消耗严重时,主要体现在 us sy wa hi 的值变高。对 JAVA 应用而言,主要体现在 us sy 两个值上:

us

us 值过高,表示运行的应用消耗了大部分的 CPU ,如下是找出具体消耗 CPU 的线程的办法:

首先通过 top pidstat 命令找出消耗 CPU 严重严重的线程及其 ID ,将些 ID 转化为十六进制的值。之后通过 kill -3 [javapid] jstack 的方式 dump 出应用的 java 线程信息,通过之前转化的十六进制的值找到对应的 nid 值的线程。该线程即为消耗 CPU 的线程。可多执行几次上述过程,以确保找到真实的消耗 CPU 的线程。

sy

sy 值高时,表示系统花费了更多的时间在进行线程切换, JAVA 应用造成这种现象的主要原因是启动的线程比较多,且这些线程多数都处于不断的阻塞和执行状态的变化过程中,导致系统不断的切换线程,产生大量的上下文切换。

5.1.2 文件 IO 消耗分析

       Linux 在操作文件时,将数据放入文件缓存区,直到内存不够或系统要释放内存给用户进程使用,因此在查看 Linux 内存状况时经常会发现可用的物理内存不多,但 cached 用了很多,这是 Linux 提升文件 IO 速度的一种做法。这种情况下,如物理空闲内存够用,通常在 Linux 上只有写文件和第一次读取文件时会产生真正的文件 IO

       Linux 中,主要通过 pidstat 来查找文件 IO 的消耗

1. pidstat

pidstat –d –t –p[pid] 1 100 查看线程的 IO 消耗状况,要在 2.6.20 以上版本有效。返回结果中, TID 表示线程 ID KB_rd/s 表示每秒读取的 KB 数, KB_wr/s 表示每秒写入的 KB 数。

. iostat

在没有 pidstat 的情况下,只能通过 IOSTAT 来查看整个系统的文件 IO 消耗状况,无法跟踪进程的文件 IO 消耗状况。

直接输入 iostat ,返回结果中, tps 是每秒的 IO 请求数 ; Blk_read/s 是指每秒读的块数量,通常块的大小为 512 字节 ; Blk_write 指每秒写的块数量 ; Blk_read/Blk_wrtn 指总共读 / 写的块数量

iostat –x xvda 3 5 输出信息会相对多一些,其中。 r/s 表示每秒读请求数 ; w/s 指每秒写请求数 ; await 表示平均每次 IO 操作的等待时间 (ms); avgqu-sz 表示等待请求的队列的平均长度 ; svctm 表示平均每次设备执行 IO 操作的时间 ; util 表示一秒之中有百分之几用于 IO 操作。

使用 iostat 时,首要关注 CPU 中的 iowait% 所占的百分比,当 iowait 占了主要的百分比时,就要关注 IO 方面的消耗状况了。

 

JAVA 应用造成文件 IO 消耗严重主要是多个线程需要进行大量内容写入 ( 如频繁的日志写入 ) 的动作;或磁盘设备本身处理速度慢;或文件系统慢;或操作的文件本身已经很大造成。

5.1. 网络 IO 消耗分析

对分布式JAVA应用而言,网络IO的消耗非常值得关注,特别要注意网卡中断是不是均衡地分配到各CPU的(通过 cat /proc/interrupts查看)。对于网卡中断只分配到一个CPU的现象,google采用了修改kernel的方法进行修复;或是采用支持MSI-X8的网卡来修复

Linux中可采用sar来分析网络IO的消耗状况。输入 sar -n FULL 1 2,执行后以1秒为频率,共输出两次网络IO的消耗情况。输出信息主要有三部分,第一部分为网卡上成功接包和发包的信息;第二部分为网卡上失败的接包和发包信息;第三部分为sockets上的统计信息。对于JAVA应用而言,主要关注第三部分的tcpsck,udpsck。

5.1. 内存消耗分析

对JVM内存的分析,第四章已有介绍,对JVM以外的内存消耗,最为值得关注的是swap的消耗以及物理内存的消耗,这两方面的消耗都可基于os的命令来查看。

1. vmstat

在命令行中输入vmstat,输出信息和内存相关的主要是memory下的swpd,free,buff,cache以及swap下的si和so。其中,swpd指虚拟内存中已使用的部分(kb);free指空闲物理内存;cache表示用于缓存的内存;swap下的si指每秒从disk读至内存的数据量;so指每秒从内存写入disk的数据量。swpd过高通常是物理内存不够用,os将物理内存中的一部分数据转为放入硬盘上进行存储。

2. sar

sar -r 会返回物理内存,swap, buffer cache等使用情况,可以认为可用的物理内存为: dbmemfree+kbbuffers+kbcached.

sar 相比vmstat的好处是可以查询历史状况,以更加准确的分析趋势状况,例如: sar –r –f /tmp/log/sa/sa12

3. top

通过 top 可查看进程所消耗的内存量,不过 top 看到的 java 进程的消耗内存是包括了 JVM 已分配的内存加上 JAVA 应用所耗费的 JVM 以外的物理内存。

4. pidstat

pidstat –r –p [pid] [interval] [times]. 执行此命令可查看进程所占用的物理内存和虚拟内存的大小。

5.1.5 程序执行慢原因分析

1.  锁竞争激烈

如数据库连接池中连接数为 10 ,有 50 个或更多线程需要进行数据操作。

2.       未充分使用硬件资源

如机器为双核 CPU ,但程序中都是单线程串行的操作

3.       数据量增长

数据量增长通常是造成程序执行慢的典型原因,当数据库中单表的数据从 100 万上涨到 1 亿后,数据库的读写速度将大幅下降

 

此外,也可借助 JProfile 等商业工具,找出执行耗时比率最大的代码。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics