性能测试之CPU分析
一、回顾:性能测试分析的思路
- 性能测试分析的思路:先分析硬件 、网络、 系统配置、应用程序
- 硬件: cpu、内存、磁盘、网络、io
- 本次我们就来谈谈cpu
二、cpu知识
-
cpu:中央处理器(central processing unit)
-
1、影响cpu性能的物理因素:架构、主频、核
- 架构:intel(x86),AMD(powerPC),ARM(ARM)
- 主频:GHz(值越高每秒刷新速度越快)
- 核心数:
-
2、结构:主要物理结构是3个,实际是有4个
- 运算器: 真正进行计算的单元
- 控制器: leader,把内存的指令,数据读入寄存器,控制计算机
- 寄存器: 暂存指令、数据、地址
- 时钟:计时
-
3、内存
- 程序代码、网络数据,外部数据进入cpu的桥梁,内存的速度,要比cpu的速度慢
-
说人话(总结)
一段程序要被执行,先编译成机器语言,进入内存。cpu控制器再从内存中获取指令,数据,放入寄存器中。时钟控制cpu的运算器什么时候开始计算,计算多久。运算器开始计算。运算过程中,如果还需要数据,控制器就从寄存器中拿数据,拿不到就从内存中拿。如果1个时间片段计算不完,就先干其他事,之后再执行。执行完了,输出数据给寄存器,传给内存–> 切换,中断
-
4、内核&线程&架构
- 内核:医院的医生,治疗病人
- 线程:医院的护士,接待病人
- 线程是cpu调度和反派的基本单位
- 1医生对1护士:单核单线程
- 1医生对 n个护士:单核多线程,超频
- 如何配置超频?
- 需要手动改配置参数
- 一般情况下企业都不会使用超频,超频就代表超负荷运行,发热过快,功耗高的时候容易出问题
- 如何配置超频?
- 架构:医院的楼层结构和医疗基础设施
- 基础越合理,工作效率越高
-
5、查看cpu信息
-
其他的常用命令
-
cat /proc/cpuinfo |grep "physical id" |sort |uniq |wc -l
查看物理cpu数量 -
cat /proc/cpuinfo | grep "cpu cores" |uniq
查看CPU的core数,即核数 -
cat /proc/cpuinfo | grep "processor" |wc -l
查看逻辑CPU数量 -
load average = cpuload + ioload
-
-
-
6、监控cpu
-
cpu 分析:
- us:用户进程空间中未改变过优先级的进程占用cpu百分比(程序在cpu进行计算的时候,没有改变过优先级,没有成为内核进行计算,在非内核计算的时间)
- 用户运行计算–>cpu密集计算 or FGC or 死循环
- cpu密集计算:代码逻辑很复杂,可能计算时候要进行密集的逻辑判断,这时候会消耗us态的时间
- FGC:
- GC:资源回收
- FGC:(Full GC)对老年代的资源进行回收。程序运行起来会分配内存资源,如果资源一直用的上,那就一直放在内存里,然后不用了再进行回收。这种回收消耗时间较长。资源回收就会带来中断和卡顿,卡顿也会导致程序暂时无响应(卡顿时间是毫秒级)
- YGC:(Young/Minor GC)新生代资源回收:资源用一次就不用了,把资源释放
- 死循环:一直在计算,用户态死循环就会占用很长时间
- 用户运行计算–>cpu密集计算 or FGC or 死循环
- sy:内核空间占用cpu百分比。
- 做上下文切换(自愿上下文切换,非自愿上下文切换)
- 上下文切换:寄存器里的资源进行切换
- 自愿上下文切换 --> 内存瓶颈
- 举例:比如进行计算时候,有10个程序,第一个程序有连续5个指令,但是在执行第三个指令的时候因为资源不够,要等待,那就切换其他进程处理其他指令。(资源不够,自觉切换到另外的指令)
- 非自愿上下文切换 -->cpu瓶颈
- 举例:执行第三个指令的时候,时间到了,这时候没有执行完,被迫中断/时间有,但是来了个优先级更高的,要立刻执行,强制中断。如果cpu够多,那就可以用另外的cpu去处理,所以是cpu瓶颈(有可能有优先级更高的指令,指令执行的时间已经到了,被迫中止当前的指令,去执行其他指令)
- 做上下文切换(自愿上下文切换,非自愿上下文切换)
- ni:用户进程空间内改变过优先级的进程占用cpu百分比(内核->非内核,或非内核->内核切换所用时间)
- 用户运行计算–>cpu密集计算 or FGC or 死循环
- id:空闲时间百分比
- wa:空闲&等待IO的时间百分比(很多时候是资源不够导致的等待)
- 等待资源 --> IO问题(磁盘/网络)
- hi:硬中断时间百分比(程序中断导致的切换(比如时间片到了))
- si:软中断时间百分比(自愿进行切换)
- 软中断 -->cpu竞争抢资源 or 资源不够IO问题
- st:虚拟化时被其余vm窃取时间百分比
- 抢占资源 --> 宿主机抢占资源
- us:用户进程空间中未改变过优先级的进程占用cpu百分比(程序在cpu进行计算的时候,没有改变过优先级,没有成为内核进行计算,在非内核计算的时间)
-
load average值和cpu使用率之间的关系
- 现在的linux服务器中,load average不等于cpu使用率
- load average是系统的整体负载体现
- 它包括 cpu负载+disk负载+网络负载+外设负载
- loadaverage=cpuload+ioload(disk+网络+外设负载都是io负载)
- cpu的使用:用户进程使用的时间us,系统内核运行时间sy,空闲时间idle,管理被抢占时间st
- 繁忙:us+sy+st+ni+hi+si cpu使用率的时间(除以总时间)
- 空间:idle+wa
-
上下文
-
上下文:cpu寄存器和程序计数器
- 程序计数器:存储cpu正在执行的指令位置和下一条指令的位置
- 程序计数器:存储cpu正在执行的指令位置和下一条指令的位置
-
上下文切换:先把当前任务的cpu上下文(cpu寄存器和程序计数器)保存起来(内核中),然后加载新任务的上下文到cpu的寄存器和程序计数器中,cpu再跳转到程序计数器上执行新任务)
-
上下文切换类型:进程上下文切换,线程上下文切换,中断上下文切换
- 进程:资源的基本单位
- 线程:调度的基本单位
-
进程上下文切换
- 特权等级,跨等级时,需要系统调用:
- 同进程上下文切换:进程用户态-- 系统调用–>进程内核态–系统调用–>进程用户态
- 不同进程上下文切换:进程切换时要保存用户态资源(虚拟内存,栈等)
- 特权等级,跨等级时,需要系统调用:
-
线程上下文切换
- 线程,共享进程的资源,但是,线程也有自己的所有数据,如栈,寄存器
- 同进程中线程上下文切换:进程资源共享,切换线程私有资源
- 好比,同一个公司,不同部门之间交流;同公司不同楼层交流
-
不同进程中线程上下文切换:切换进程
-
-
cpu性能分析:load高 && cpu高
- top
- 情况1:sys系统态高 --> 需要排查cpu上下文切换
- 如果非自愿上下文切换多,说明cpu不够用,进程时间片刻,被迫切换
- 如果自愿上下文切换多,说明计算用的资源不够用,可能存在IO,内存瓶颈
- 情况2:si软中断高 --> cpu抢资源,资源不够用IO问题
- sys高+si高 --> 推导出:内存 or网络IO问题 --> 解决方法:排查内存和IO
- sys高+si不高 --> 推导出:cpu瓶颈 --> 解决方法之一 :加cpu
- 情况3:us用户态高 --> 用户程序计算
- 密集型计算,内存FGC,资源等等(线程池)–>解决方法:逐个排查
- 情况1:sys系统态高 --> 需要排查cpu上下文切换
- top
-
做性能测试时候每次的结果都相差很大/不准,怎么分析?
- 如果是用无线网络测试的,可能会出现数据传输不稳定,出现延迟,导致结果会出现较大出入。我们就需要监控网络情况。有以下几种方式:
- 1,jmeter聚合报告最后两列,可以利用这两个值计算出带宽。企业可能用千兆光纤,但是企业的服务器一般只有几兆到几十兆。
- 2,也可以通过监控方式,如果有云服务器的管理台,可以看下管理台的网络流量图。
- 3,直接ping被测服务域名/ip,看看网络的延迟时间。如果时间在几毫秒~几十毫秒以内,那是可以接受的。我们可以在没有做测试前可以ping一下,正在做测试过程中也ping一下,看看有没有明显增大,如果增大非常多,甚至出现丢包,那就说明延迟已经影响性能测试,网络已经成为瓶颈。
- 如果是用无线网络测试的,可能会出现数据传输不稳定,出现延迟,导致结果会出现较大出入。我们就需要监控网络情况。有以下几种方式:
三、cpu实战
-
1、测试前准备
-
1、查看loadaverage是否正常
- 真正在做性能测试时,你要管理好你的被测服务器,loadaverage要恢复正常,第一个值,没有明显的上升或下降的趋势,也就是说第1个值要基本不变。
-
2、安装监控
- 这里用的grafana+prometheus + 硬件资源\应用资源(详情可以去看我另外一篇博客)
- 服务器硬件资源监控: grafana(前端) + prometheus(时序数据库) + node_exporter(硬件资源收集器)
- 被测服务器上 部署 node_exporter
- node_exporter上传到被测服务器
- 解压、启动
./node_exporter
- 端口:9100
- 监控平台机器上,启动 grafana + prometheus
- 进入prometheus文件夹,修改Prometheus.yml的配置文件
- 保存好配置文件,启动Prometheus
./prometheus
默认端口:9090 - 启动grafana
systemctl restat grafana-server
默认端口: 3000 - http://grafanan_ip:3000 admin admin
-
-
(( proc_cnt = `nproc`*10 )); stress-ng --cpu $proc_cnt --pthread 1 --timeout 150
# nproc 这个命令可以获得服务器cpu的数量
# (( proc_cnt = `nproc`*10 )); 把cpu核的数量乘以10倍,给变量proc_cnt
# --cpu $proc_cnt $proc_cnt shell编程中的变量引用
# --pthread 每个进程有多少个线程
# --timeout 超时时间,在命令执行多长时间之后自动结束
-
压测前:
-
我们开始压测:
再看top命令,loadaverage,task,cpu的us,sy明显增大了
-
查看vmstat 1
-
查看 pidstat -w 1
-
结束后,数据慢慢降下来
-
查看grafana监控平台
总结
-
1、top命令,可以到 loadaverage 有持续上升,cpu被100%使用 us + sy + si
-
2、 vmstat proc中r列有非常大的数据 有非常多的进程在抢cpu的资源
- memory: free 数据变小, 内存有一部分被使用、
- system: in有一点点, cs 有明显数据变大,说明有大量的 上下文切换
-
3、 pidstat -w 1----这个命令可以上下文的信息。我们看到的大量 stress-ng–cpu cswch/s 自愿和nvcswch/s非自愿上下文的值。现在可以得出 ,我们线程有大量的 进程上下文切换问题,而这个问题的进程:stress-ng–cpu。
分析思路
1、首先我们使用top命令发现服务器的系统负载比较高,所有的cpu的使用率接近或等于 100%,我们要排查这个问题。
2、我们使用vmstat 1命令,发现procs 中r列有大量数据,说明我们有大量进程在竞争cpu的资源。可能服务器的cpu数量不够, 也可能是进程启动的太多导致。我们还看system中cs比较高,表示肯定有大量的上下文切换。但是此时我们并不知道是哪个进程导致 抢占cpu,我们需要找出具体是哪个进程。应该是某个经常有大量的上下文切换,而导致的cpu使用率过高,系统负载过高的问题。
3、接着我们使用pidstat -w 3命令,看到具体的上下文切换的数据比较大的进程,得到具体进程 和进程id:stress-ng–cpu
# 该命令会在n个cpu核的系统上,产生n个线程,模拟线程间竞争cpu的场景
stress-ng --cpu `nproc` --pthread 1024 --timeout 60
- 分析命令:
- top
- vmstat 1
- pidstat -w 5
- 结果如下
总结
-
1、top: load值一直在增加,而且增长的非常大
-
2、top:CPU的 us + sy ≈ 100%,us较低,sy较高
-
3、vmstat: procs的r 就绪队列长度,正在运行和等待的CPU进程数很大
-
4、vmstat: system的in(每秒中断次数) 和 cs(上下文切换次数) 都很大
-
5、vmstat:free变小、buff基本不变、cache变大
-
6、pidstat: cswch/s 自愿上下文切换 升高
分析思路
- 首先我们使用top命令进行分析,得出如下结论:
- loadaverage 上升
- cpu: wa值很大 us、sy不是很大, buff/cache有增大
- 然后我们使用vmstat进行分析(vmstat 1),得出如下结论:
- mem free减少, cache有明显的增大,bo有明显数据,说明有大量磁盘数据交换
- 然后我们再使用mpstat -P ALL 3进行分析,发现 %iowat 数值比较大,再次证明,我们线程系统负载比较高的原因是系统的磁盘读写测试性能瓶颈,那到底是哪个进程导致我们的磁盘读写高?我们使用pidstat -w 1命令,发现stress-ng-hdd这个进程的自愿上下文切换数据比较大
解决方案
- 换磁盘
- 迁移到io性能更好的服务器。如果你是整体的迁移你的数据库,这个风险比较大,我们可以再另外一个IO性能比较好服务器,再安装一个数据库,做数据库的读写分离
- 减少io操作(有的时候日志打多了会造成这样的情况,可以调高日志的级别)
四、性能测试如何定位到具体代码
思路:具体进程id之后, 找到进程线程id,然后把线程id进行16进制转换, 进程id日志打印出来,过滤出线程id(16进程),后面会详细讲解
五、高频面试题
1、性能测试监控到cpu使用率很高,如何定位问题?
答:我们可以通过top,vmstat,pidstat命令进行定位
1、通过top命令判断是用户态还是系统态问题
2、通过vmstat定位process是r还是b列
3、通过pidstat具体看是自愿上下文还是非自愿上下文,看到具体的上下文切换的数据比较大的进程
2、性能测试服务器很卡,但是资源利用率不高,如何定位?
答:top命令查看wa的值是不是比较高,是的话说明有IO问题,我们再用iostat查看具体是哪一块导致的
3、性能测试出现内存泄露,如何定位?
答:通过jmap或者arthas来dump下内存的信息,通过MAT分析工具定位到代码问题,给开发人员看
4、性能测试前期正常,后期报错,怎么分析?
答:1、看报错信息,可能是网络堵塞
2、看系统负载是否恢复正常再开始测试
3、源端口是否够用
4、根据报错信息,具体分析
5、性能测试tps上不去,但是cpu资源使用率不高,怎么分析?
答:可能是以下的有问题
- 网络带宽
- io
- 连接池:应用连接池、数据库连接池过小,默认151
- 资源没有及时回收: gc、堆栈配置
- 数据库的配置:比如报错too many connections
- linux服务器的配置
- 通信连接机制:websocket协议比http协议性能好很多
- 硬件:内存太小,网卡速度太慢
- 脚本本身有问题:比如脚本加了beanshell
- 压力机太少,可以使用分布式
- 业务逻辑:比如被测服务器业务逻辑复杂,性能本身就比较差
- 系统架构:把代码写在一个地方肯定比不上拆分成微服务