登录 |  注册
首页 >  架构·案例 >  架构师学习之路-Java开发实战学习笔记 >  java线程切换消耗时间排查-借助top指令对cpu消耗分析

java线程切换消耗时间排查-借助top指令对cpu消耗分析

top指令.png

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

1、上下文切换

每个CPU在同一时间只能执行一个线程,Linux采用的是抢占式调度,即为每个线程分配一定的执行时间,当到达执行时间、线程中有IO阻塞或高级优先线程要执行时,Linux将切换执行线程,在切换时要存储目前线程的执行状态,并要恢复要执行的线程状态,这个过程称为上下文切换。对于java应用,典型的是进行文件IO操作、网络IO操作、锁等待或线程sleep时,当前线程会进入阻塞或休眠状态,从而促发上下文切换,上下文切换过多会造成内核占据较多的CPU使用,使得应用的相应速度下降。

2、运行队列

每个CPU核都维护了一个可运行的线程队列,例如一个4核的CPU,JAVA应用中启动了8个线程。且这8个线程都初一可运行的状态,那么在分配平均的情况下每个CPU中运行队列里就会有两个线程。通常而言,系统的load主要由cpu的运行队列来决定,假定以上状况运行维持了1分钟,那么这1分钟内系统load就会是2,但用于load是个复杂的值,因此也不是绝对的,运行队列值越大,就意味着线程会要消耗长时间才能执行完。Linux System and NetWork Performance Monitoring中建议控制在每个cpu核上的运行队列为1~3个。

3、利用率

CPU利用率为CPU在用户进程、内核、中断处理、IO等待以及空闲五个部分使用百分比,这5个值用来分析CPU消耗情况的关键指标。Linux System and NetWork Performance Monitoring中建议用户的CPU消耗/内核的CPU消耗的比率在65%~70%/30%~35%左右。

使用top命令查看

top - 23:22:02 up  5:47,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 107 total,   1 running, 106 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.3%us,  0.3%sy,  0.0%ni, 99.3%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1017464k total,   359292k used,   658172k free,    56748k buffers
Swap:  2064376k total,        0k used,  2064376k free,   106200k cached

此信息关注第三行信息

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

对于多核或者对歌CPU,上面的显示或是多个cpu所占用的百分比的综合,因此会出现160%us这样的现象,如需要查看每个核的消耗情况,可在进入top视图后按1,就会按核来显示消耗情况

默认情况下top视图中显示的为进程的CPU消耗状况,在top视图中按shift+h后,可按线程查看CPU的消耗状况,

1313 root      20   0  165m 3848 3024 S  0.0  0.4   0:05.06 vmtoolsd
2767 xubo      20   0 14940 1176  904 R  0.3  0.1   0:02.93 top
1 root      20   0 19228 1428 1148 S  0.0  0.1   0:01.86 init
1949 root      20   0  150m  20m 4976 S  0.0  2.0   0:01.58 Xorg
2076 gdm       20   0  363m  14m  10m S  0.0  1.5   0:01.01 gdm-simple-gree

还可以使用pidstat  vmstat

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

当CPU消耗严重时,主要体现在us、sy、wa或hi的值变高,wa的值是IO等待造成的,hi的值变高主要是硬件中断造成的,例如网卡接收数据频繁的状况。

对于java应用而言,CPU消耗严重主要体现在us、sy两个值上,分别看看java应用在两个值高的情况下应如何寻找对应造成平静的 代码。

1 、us

当us值过高时,表示运行的应用消耗了大部分的CPU。在这宗情况下,对JAVA应用而言,最重要的为找到具体消耗CPU的线程所执行的线程执行代码,可采用如下犯法做到。

首先通过linux提供的命令找到消耗CPU严重的线程及其ID,将线程ID转化为十六进制的值。之后通过 kill -3 [javapid]或jstack的方式dump出应用的java线程信息,通过之前转化出的十六进制的值找到对应的nid值的线程。该线程即为消耗CPU的线程,在采样时候须执行几次上述的过程,确保找到真实消耗CPU的线程

java应用造成us高的原因主要是线程一直处于可运行状态,通常是这些线程在执行无阻塞、循环、正则或纯粹的计算等动作造成;另外一个可能是频繁GC。如每次请求都需要分配较多的内存,当访问量搞的时候就将导致不断地进行GC,系统响应速度下降,进而造成堆积的请求更多,消耗的内存更严重,最严重的时候有肯能会导致系统不断的惊醒Full GC,对于频繁GC的状况要通过分析JVM内存消耗来查找原因

2、sy

当sy值高时,表示Linux花费了更多的时间在进行线程切换,Java应用造成这种现象的主要原因是启动的线程比较多,且这些线程多数处理不断的阻塞(如锁等待、IO等待状态)和执行状态的编号过程中,这就导致了操作系统要不断切换执行的线程,产生大量的上下文切换。在这种状况下,对Java应用,最重要的是找出线程不断切换状态的原因。

上一篇: 什么是SOA (面向服务的架构)
下一篇: Java强软弱虚四种引用,看完不再犯迷糊
推荐文章
  • 一.概述我们在考虑MySQL数据库的高可用的架构时,主要要考虑如下几方面:如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中断。用作备份、只读副本等功能的非主节点的数据应该和主节点的数据实时或者最终保持一致。当业务发生数据库切换时
  • 一步一步推导出Mysql索引的底层数据结构。  Mysql作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤其是Mysql数据的存储形式以及索引的设计,决定了Mysql整体的数据检索性能。我们知道,索引的作用是做数据的快速检索,而快速检索的实现的本质是数据结构。通过不同数
  • 如何看到老年代、新生代的对象有哪些呢?MAT是分析dump的神器(顺便吐槽:当然也是吃内存卡机器的怪兽)。通常我们会在出现fullGC时dump下堆内存,然后分析FullGC的原因。那如何获知整个堆内存里,有哪些对象在新生代、哪些在老年代呢?一个典型的应用场景是:出现了耗时超预期的YoungGC,我
  • 面向服务的架构(SOA)是一种软件开发方法,它使用称为服务的软件组件来创建业务应用程序。每项服务提供一种业务能力,并且服务也可以跨平台和语言相互通信。开发人员使用SOA来重用不同系统中的服务,或者组合几个独立的服务来执行复杂的任务。例如,一个组织中的多个业务流程需要用户身份验证功能。您可以创建一项身
  • 1.背景1.1什么是交互式推荐?交互式推荐是一种互动式实时推荐产品模块,主要通过理解用户需求、以互动的方式进行推荐。交互式推荐由Youtube在2018年提出,主要用于解决推荐系统的延迟和与用户互动偏弱的问题。从2021年下半年开始,美团外卖推荐技术团队在外卖首页Feed上持续进行探索,2022上半
  • 导读:老是出现堆内存不足,大量FullGC深知出现内存溢出应该怎么办,怎样通过排查找到源头分析来解决问题?正文:我们有个新服务上线运行一段时间后,老是出现堆内存不足,大量出现FullGC,有些实例甚至出现内存溢出错误:java.lang.OutOfMemoryError:Javaheapspace但
学习大纲