通常情况下,性能报告中只说CPU使用率高的时候,并不能帮助定位问题。因为CPU高会有多种不同的情况。CPU有五种状态(us sy id wa st), 在vmstat中能显示出来,这个想必很多人都清楚。在代码消耗CPU的时候(这也是通常性能分析中会遇到的),是US状态的CPU。当然还存在一种情况,就是代码产生的系统调用特别高,这种情况下SY的CPU也会高(这种情况比较少见,在我的职业生涯中只见过一次)。对于JAVA语言来说,我们不需要特别复杂的profile工具就可以做到定位到代码。

在写具体的分析方法之前,需要说一下线程的状态转换关系,我们先来看一下系统级的线程状态转换关系。

通过这个转换关系,可以看到,在线程产生之后,会先到ready的状态。在这个状态上是在等待CPU的。而在runing状态才是真正在CPU上执行的。请注意这个区别。

而vmstat显示的 r 列是包括了ready和running的线程(会因操作系统的不同有区别,但是对大部分linux系统都是这样)。请注意这一点,因为网上有很多在写vmstat的解释的时候,说 r 列是表示正在运行的进程数或者说 r 是表示正在运行的线程数,这一点是不对的。给大家看一个例子(这也是下面要说到的例子):

这是我的一个云服务器上正在运行的top。可以看到当前tasks(进程)中只有一个是running的状态的。而这时的vmstat呢?

这个服务器只有两个CPU,所以如果r是说正在运行的进程或线程数的话肯定是不正确的,因为两个CPU同时运行的最多是两个线程。

所以请记住,这个 r 值就包括了等待CPU的线程(也就是ready状态的)和正在运行的线程(也就是running状态的)。

以后有时间再解释其他系统级的线程状态,可能有些人觉得其他状态也没什么好解释的,但是在性能分析中,线程的状态和一些性能计数器是有关联关系的,比如说suspended状态是CPU时间片用完导致暂时被换出;而blocked是因为要等待某个条件被满足而阻塞;并且这两种状态都有可能导致CPU使用率高。在分析的过程中,这些信息给我们的是一个方向。所以前面说到仅说CPU高不能帮助分析问题,因为CPU高有多种原因。

因为下面要说的是JAVA,所以来看一下JAVA的线程状态转换关系。

从这个图中,我们可以看到JAVA的进程有多种状态(具体状态的解释请自行搜索),怎么看到这些状态都在干什么,就需要把栈打出来看。在栈中,可以看到具体对应的代码(对其他编译语言来说,要看看到正在运行的code也是要看栈的)。另外,在性能分析中,栈的分析是非常重要的一块内容,今天因为只是为了说明从CPU高怎么定位到代码层,所以不过多解释线程的状态了,以后有时间再写文章说明。

实例:

下面来操作一下,首先执行一个消耗CPU的JAVA实例(实例是7D Group成员所编,有兴趣动手操作的可以到网上随便找一个小例子或自己编写一个)。查看vmstat的状态。

从上图可以看到左边窗口在执行一个消耗CPU的Demo,而右边的窗口看到当前系统的CPU已经完全被消耗掉了。进程号通过top命令就可以知道:

下面就要看一下这个进程中的哪些线程消耗了CPU。

通过pidstat可以看到(不好意思的是,pidstat的截图被我覆盖掉了,又不想重新开始所以就不截图啦),有10个线程消耗着CPU资源。我把命令放在这里,有兴趣的可以自己操作。

pidstat -p 10846 -u -d -t -w -h 1 1000

从上命令可以看到,有多个线程消耗着CPU。线程ID是:10861、10862、10863等等。

用jstack做一下thread dump。

[root@7dgroup ~]# jstack -l 10846 > 10846.threaddump

再打开这个生成的文件。

nid是指native ID,对应着系统级的tid。只不过TID显示的是10进程的,NID显示的是16进制的。

我们转换一个线程号来查找。

[root@7dgroup ~]# printf %x'\n' 10861

2a6d

再对应到threaddump文件中。

显然可以去查这个CPUTestThreadDemo.java的第13行了。

从这个例子可以看出,对java的代码消耗CPU高的分析只需要通过系统级的命令和JDK自带的命令就可以完成了。因为这个例子非常简单,步骤比较清楚。但在实际分析代码众多,逻辑复杂的应用,有可能你看到的是CPU在线程上的消耗是在不停的切换的,所以就需要多做些thread dump,一个个分析。当然借助些工具分析,通常可以让我们在分析复杂的应用时事半功倍。

这里只说明一个思路。

对JAVA的分析来说,已经有非常多的人写了非常多的文章了,我之所以写这个文章,是为了让文章能更系列一些。

  •  
     
     
 

性能分析之CPU分析-从CPU调用高到具体代码行(JAVA)的更多相关文章

  1. 性能分析之CPU分析-从CPU调用高到具体代码行(C/C++)

    今天在培训的过程中,也提到了分析要具体到代码的事情,如果思路方向是正确的,对java应用和C/C++应用来说,也是几个命令就可以跳到代码行了.前提是要能看得懂堆栈信息.所以一直以来我在讲课的过程中都有 ...

  2. Python 获取被调用函数名称,所处模块,被调用代码行

    获取被调用函数名称,所处模块,被调用代码行 by:授客 QQ:1033553122 module2.py: #!/usr/bin/env python # -*- coding:utf-8 -*- _ ...

  3. PC虚拟现实应用的性能分析与优化:从CPU角度切入

    如今,虚拟现实 (VR) 技术正日益受到欢迎,这主要得益于遵循摩尔定律的技术进步让这一全新体验在技术上成为可能.尽管虚拟现实能给用户带来身临其境般的超凡体验,但相比传统应用,其具有双目渲染.低延迟.高 ...

  4. DIY Ruby CPU 分析——Part I

    [编者按]原文作者 Emil Soman,Rubyist,除此之外竟然同时也是艺术家,吉他手,Garden City RubyConf 组织者.本文是DIY Ruby CPU Profiling 的第 ...

  5. DIY Ruby CPU 分析——Part III

    [编者按]作者 Emil Soman,Rubyist,除此之外竟然同时也是艺术家,吉他手,Garden City RubyConf 组织者.本文是 DIY Ruby CPU Profiling 的第二 ...

  6. DIY Ruby CPU 分析 Part II

    [编者按]作者 Emil Soman,Rubyist,除此之外竟然同时也是艺术家,吉他手,Garden City RubyConf 组织者.本文是 DIY Ruby CPU Profiling 的第二 ...

  7. 使用ANTS Performance Profiler&ANTS Memory Profiler工具分析IIS进程内存和CPU占用过高问题

    一.前言 最近一段时间,网站经常出现两个问题: 1.内存占用率一点点增高,直到将服务器内存占满. 2.访问某个页面时,页面响应过慢,CPU居高不下. 初步判断内存一点点增多可能是因为有未释放的资源一直 ...

  8. linux概念之cpu分析

    http://ilinuxkernel.com/?cat=4 Linux CPU占用率原理与精确度分析1  CPU占用率计算原理在Linux/Unix 下,CPU 利用率分为用户态.系统态和空闲态,分 ...

  9. jstack来分析。当linux出现cpu被java程序消耗过高时

    我们使用jdk自带的jstack来分析.当linux出现cpu被java程序消耗过高时,以下过程说不定可以帮上你的忙: 1.top查找出哪个进程消耗的cpu高 21125 co_ad2    18   ...

随机推荐

  1. python常识系列07-->python利用xlwt写入excel文件

    前言 读书之法,在循序而渐进,熟读而精思.--朱熹 抽空又来写一篇,毕竟知识在于分享! 一.xlwt模块是什么 python第三方工具包,用于往excel中写入数据:(ps:只能创建新表格,不能修改表 ...

  2. 【Docker】2. Docker的架构介绍、安装与卸载 (CentOS 7)

    一.docker的基本组成 开局一张图. docker的组成: Client:客户端,可以通过它与docker服务进行交互.比如容器的构建.拉取.运行. DOCKER_HOST:就是docker服务. ...

  3. python函数默认值只初始化一次

    当在函数中定义默认值时,值初始化只会进行一次,就是执行到def methodname时执行.看下面代码: from datetime import datetime def test(t=dateti ...

  4. 如何实现一个简易版的 Spring - 如何实现 AOP(上)

    前言 本文是「如何实现一个简易版的 Spring 系列」的第五篇,在之前介绍了 Spring 中的核心技术之一 IoC,从这篇开始我们再来看看 Spring 的另一个重要的技术--AOP.用过 Spr ...

  5. DataGear 变更部署数据库为SQL Server填坑指南(含转写后的SQL server代码及SQL server配置文件)

    1. 引言 2. 配置数据库链接 3. 引入数据库驱动 4. 手动初始化数据库 5. 改写SQL 6. 其他 7. 参考 1. 引言 DataGear默认使用Derby数据库作为系统的元数据库,至于待 ...

  6. [Scala] 面向对象

    类定义 当属性是private时,scala会自动为其生成get和set方法 只希望scala生成get,不生成set,可定义为常量 不生成get和set方法,使用private[this]关键字 1 ...

  7. 【转载】基于Linux命令行KVM虚拟机的安装配置与基本使用

    基于Linux命令行KVM虚拟机的安装配置与基本使用 https://alex0227.github.io/2018/06/06/%E5%9F%BA%E4%BA%8ELinux%E5%91%BD%E4 ...

  8. 怎样使用yum-cron为CentOS7自动更新重要的安全补丁

    怎样使用yum-cron为CentOS自动更新重要的安全补丁 2017年4月19日 | 分类: [技术] 参考:https://linux.die.net/man/8/yum-cron参考:http: ...

  9. 015.Python函数名的使用以及函数变量的操作

    一 函数名的使用 python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限 1.1 函数名是个特殊的变量,可以当做变量赋值 def func(): p ...

  10. linux中cat、more、less命令区别详解##less 最合适最好用,和vim一样好用

    linux中cat.more.less命令区别详解 caoxinyiyi关注 0.0362018.07.02 15:46:17字数 641阅读 516 linux中命令cat.more.less均可用 ...