Fork me on GitHub

性能监控

改善性能有三个步骤要做:性能监控、性能分析、性能调优
性能监控是一种以非侵入式方式收集或查看应用运行性能数据的活动。
性能分析是一种 以侵入式方式收集运行性能数据的活动,它会影响应用的吞吐量和响应性。性能分析很少在生产环境中进行,通常是在质量评估、测试或者开发环境中,一般是性能监控之后的行为。
性能调优是一种为改善应用响应性或吞吐量而更改参数、源代码或属性配置的活动。

cpu使用率

分为用户态CPU使用率系统态CPU使用率。用户态使用率是指执行应用程序代码的时间占总CPU时间的百分比。系统态CPU使用率是指应用执行操作系统调用的时间占总CPU时间的百分比。
系统态CPU使用率高意味着共享资源有竞争或者IO设备之间有大量的交互。提高应用性能和扩展性的目标是尽可能的降低系统态CPU使用率。

命令行监控CPU使用率 Linux

Linux的vmstat显示所有虚拟处理器的总CPU使用率。不指定vmstat的报告时间间隔,则输出自系统最近一次启动以来总CPU使用率。us是用户态CPU使用率,sy是系统态CPU使用率,id是空闲率。us+sy=100-id。
top命令可以查看具体的进程占用的CPU使用率,上半部分是概要信息,下半部分是具体的进程占用的CPU使用率。 1.jps
查看当前运行的java应用线程的pid
2.jmap -heap pid
查看pid运行的堆栈各个年代区域的内存占用
3.jstat -gcutil pid
查看当前进程gc的次数和gc时间
4.ps -mp pid -o THREAD,tid,time
查看cpu占用高的线程
5.top -Hp pid
查看最耗时的线程
6.printf "%x" tid
转换线程id为16进制表示
7.jstack pid |grep tid -A 30
打印问题线程的堆栈信息 -A 表示取tid后30行
8.jstack pid >>jstack.out
导出进程的堆栈信息到文件

ps axf 查看僵尸进程 kill 掉僵尸进程的父进程
java -XX:PrintFlagsInitial | grep MetaspaceSize 查看元空间的大小
NewRatio 为2时代表新生代与老年代的内存比为1:2,新生代为整个堆的1/3.
在设置了-XX:MaxNewSize的情况下,-XX:NewRatio的值会被忽略

CPU调度程序运行队列

监控CPU调度程序运行队列对于分辨系统是否满负荷也有重要意义。运行队列中就是那些已准备好运行、正等待可用CPU的轻量级进程。如果准备运行的轻量级进程数超过系统所能处理的上限,运行队列就会很长。运行队列长表明系统负载肯已经饱和。当运行队列长度达到虚拟处理器的4倍或更多时,系统的响应就非常迟缓。
指导原则如果在很长一段时间里,运行队列的长度一直超过虚拟处理器个数的1倍,就需要关注了,只是暂时还不需要立刻采取行动。
解决运行队列长的两种办法
1.增加CPU以分担负载或者减少处理器的负载量。
2.减少应用所需CPU周期,如减少垃圾收集的频度或者采用完成同样任务但CPU指令更少的算法。java程序员可以通过更有效的算法和数据结构来实现更好的性能。
监控CPU调度程序运行队列,linux可以使用vmstat命令监控运行队列长度,vmstat输出的第一列是运行队列长度,值是运行队列中轻量级进程的实际数量。

内存使用率

除了CPU使用率,还需要监控系统内存相关的属性,例如页面调度或页面交换、加锁、线程迁移中的让步式和抢占式上下文交换。
系统在进行页面交换或者使用虚拟内存时,Java应用或JVM会表现出明显的性能问题。当应用运行所需内存超过可用物理内存就会发生页面交换,为了应对这种情况,通常要为系统配置swap空间,swap空间一般在独立的磁盘分区上。
JVM垃圾收集器在系统页面交换时的性能也很差,这是由于垃圾收集器为了回收不可达对象所占用的空间,需要访问大量的内存。
如果发现垃圾收集时间变长,系统有可能正在进行页面交换,为了验证这一点,必须监控系统页面交换。 linux下可以使用vmstat命令观察si so的值的变化,si列显示页面换入开始快速增加,通常说明系统中有应用或者一组应用在进行大量的内存分配或者内存访问。当物理内存逐渐耗尽时,系统开始将最近最少使用的内存置换到虚拟内存。

监控锁竞争

java5之前是依赖操作系统原语的方式实现锁优化逻辑,这可以通过查看系统CPU使用率和互斥量上自旋次数来监控Java应用中的锁竞争。Java5及以后版本HotSpot VM以后用户代码实现了许多优化锁逻辑,使用工具看系统态CPU使用率的方法无效了。
Java5以上版本线程通过忙循环自旋尝试获得锁,如果若干次忙循环自旋之后仍然没有成功,则挂起该线程,等待被唤醒再次尝试获取该锁。挂起和唤醒线程都会导致操作系统的让步式上下文切换,因此锁竞争严重的应用表现为出现大量让步式上下文切换,而让步式上下文切换耗费的时钟周期代价非常高,通常高达80000个时钟周期。
自旋锁的通俗解释,在物理机器有多个处理器的系统中,可以同时有两个线程并行,假定他们会同时获取某个共享数据的锁,由于多数应用只会在很短时间内锁住共享数据,所以对这两个线程而言,后尝试获取锁的线程没有必要直接挂起,可以先执行忙循环自旋等待一会,然后再尝试获取该锁。对于锁占用时间短的应用来说,自旋锁改善性能的效果非常好,但是对于占用时间长的锁来说,反而是加重了性能损失。
Linux下计算让步式上下文切换每秒占用的时钟周期的比例。安装sysstat工具使用pidstat -w -I -p pid 5命令,可以看到每5秒监控进程id为pid的Java应用的上下文切换次数cswch/s。计算让步时钟周期占用是3%以上就表示Java应用正面临锁竞争。

上下文切换

抢占式和让步式,抢占式表示线程因为分配的时间片用尽而被迫放弃CPU或者被其他优先级更高的线程所抢占,让步式是指执行线程主动释放CPU。

网络I/O使用率

分布式Java应用的性能和扩展性受限于网络带宽或网络I/O的性能。举例来说,如果发送到系统网络接口硬件的消息量超过了它的处理能力,消息就会进入操作系统的缓冲区,这会导致应用延迟。
Linux可以使用nicstat工具监控网络使用率,下面是相关列的含义
Int 网络接口设备名
rKb/s 每秒读取的KB数
wKb/s 每秒写入的KB数
rPk/s 每秒读取的包数
wPk/s 每秒写入的包数
rAvs 每秒写入的平均字节数
%Util 网络接口使用率
Sat 饱和度
通过nicstat判断分布式Java应用是否使网络饱和。

应用性能改进的考虑

  • 减少系统态CPU的策略是减少网络读写的系统调用
  • 使用非阻塞的Java NIO而不是阻塞的java.net.Socket,减少处理请求和发送响应的线程数。
  • 从非阻塞socket中读取数据的策略是,应用在每次读请求时尽可能多地读取数据。当往socket中写数据时,每个写调用应该尽可能多地写。

磁盘I/O使用率

对于有磁盘操作的应用来说,查找性能问题,就应该监控磁盘I/O。例如数据库。
Linux使用iostat -xm 5命令查看磁盘I/O使用率和系统态CPU使用率。
关于磁盘性能,有一个经常被忽视的方法,就是检查磁盘缓存是否开启。有一些系统将磁盘缓存设置为禁用,开启磁盘缓存可以改善严重依赖磁盘I/O的应用的性能。然而,如果发现系统默认设置为禁用磁盘缓存,就应该注意,因为一旦开启磁盘缓存,意外的电源故障可能会导致数据损失。


最新评论

    还没有人评论...

当当

友情链接

Powered by Python. Copyright © 2017.

鄂ICP备17010875号. All rights reserved.