什么是性能优化
性能优化就是发挥机器本来的性能。
所以我们要做的就是让机器性能发挥至最大。
遇到性能问题怎么办
不要慌,因为你一时半会也解决不了。
到底是不是问题?
观看架构图
从上往下定位是否存在问题
若存在问题是什么地方存在问题,哪一行代码?
注意网关
机器性能观看的几个维度CPU MEMORY IO NETWORK。遇到性能问题,不一定只会是jvm的问题,可能是使用这个环境机器的问题。
CPU
:首先检查 cpu,cpu 使用率要提升而不是降低
CPU 空闲并不一定是没事做,也有可能是锁或者外部资源瓶颈。
查看入口层的服务器,所有的性能都要在cpu中处理,首先查看CPU.
load average:平均负载 代表1分钟 5分钟 15分钟的繁忙程度
%cpu:消耗的情况
测试:
一个springboot的demo jar包
可以看到我们的项目启动占用了cpu的部分资源
访问bad路径进行增加服务器的负载
而访问我们其他的正常资源路径的时候仍然是没问题的(忘记截图)
可见看到cpu被占满可显示100.0us(上图中第三行的位置) 说明我们的cpu是单核的,也可以在其他地方可以看到。
若是多核cpu将会继续占用其他核的cpu资源。比如:200%,300%的占用。和我们windows类似,若占用资源过高,电脑处理不及时,会有种卡的表现。但不代表不能用。
#也能查看到cpu的信息 编号从0开始
cat /proc/cpuinfo
或者是在top命令状态下按1也可查看
有几个cpu就会出现几个cpu(number)
cpu占用过高或者是占满,我们为什么还是能正常访问资源?
线程会切换(top的动态显示标题栏中是不会占用到100%的,cpu底层的时间片单位会不断的切换,时间片的调度是不一样的,策略很复杂),所以是可以正常访问的。
top命令可以帮助我们查看哪个进程的cpu占用过高
哪一行代码造成的?
通用方法
- 看日志
- jstack(更方便)
jstack 进程pid > a.txt
我这里的是13905
即 jstack 13905 > a.txt
(jstack 用的是进程号,这里没有使用线程号,有的说切到线程模型然后定位线程,但是在使用线程模型进行stack的时候会有没搞明白的错误,所以在这里使用jstack 进程号)
a.txt已经生成,现在就可以进行定位代码
jstack打的是进程的dump,所以我们要去dump中去找线程的执行过程
现在我们要获得我们线程号 转换到16进制,在其a.txt中进行定位
top命令中 shift+h转换到线程模型
转换16进制
printf "%x \n" 13923
3663
在a.txt中搜索3663
定位到错误
Memory
#一秒钟打印一次内存情况
vimstat 1
#或者
free -g
代表有3个G的内存空间,2个G的free,其中buffers是优化我们机器读写操作,是用来承接写的一个一个块(IO读写消耗大),读用的就是cached,二者都是为了提升读写速度。
当内存很大的时候,我们就要关注内存模块了.
IO
#可以看到我们的读速度和写速度(df -h是看的是我们的文件的大小)
iostat -dx 1
访问相关路径可以看到我们的写速度和等待速度明显提升,但更关键的是%util,12.2%相当于是1秒的12.2%的时候在做IO,通常%utils是很小的,svctm代表是功能用了多久,await是执行等待的时间,若一直读写的时候是会一直增长。若是定位问题的话,只能从业务层面去定位。并不能像CPU那样定位代码。
Network
#linux中是没有单纯的命令去看netstat的信息,需要外装一工具 nicstat
nicstat
rKB/S: 每秒接收到千字节数。
wKB/S: 每秒写的千字节数。
术语介绍
吞吐量TPS: 单位时间内完成的工作量。
平均响应时间: 提交请求和返回该请求的响应之间使用的时间。
平均响应时间越短,系统吞吐量越大;平均响应时间越长,系统吞吐量越小;但是,系统吞吐量越大,不代表平均响应时间越小(有时吞吐量的增大,有时会把平均响应时间作为牺牲,来换取时间处理更多的请求)。
QPS:单个进程每秒请求服务器的成功次数
是问题,怎么证明是问题
能复现问题。以上介绍的情况是最常见的一种情况。
梳理思路
找到cpu高的线程号,所有的方法都执行在线程中,肯定的相应的方法有问题。jvm提供的一个命令jstack,jstack中后跟的线程/进程 相应的线程干了什么,我们能定位到其中,对应的是我们线程中pid的16进制,定位代码。
本文介绍了性能优化关于CPU的介绍以及处理,其他方面的性能优化,后续更新。