专栏首页7DGroup性能测试之java程序观察简单步骤

性能测试之java程序观察简单步骤

背景

在做性能测试中不断思考java应用,性能怎么观察,怎么通过方法定位到代码,是否有通用步骤,通过查找资料与查看网上知识、帮助文档之后,才有如下文章,话说知道不等于会,会不等于能运用,只有不断有意识去练习才能掌握。

操作步骤

  • 使用TOP命令找到谁在消耗CPU比较高的进程,例如pid = 1232
  • 使用top -p 1232 单独监控该进程
  • 输入大写的H列出当前进程下的所有线程
  • 查看消耗CPU比较高的线程,并看线程编号,例如 12399
  • 使用jstack 1232>pagainfo.dump 获取当前进程下的dump线程信息
  • 将第四步获取的线程编号12399转换成16进制306f (printf "%x\n" 12399)
  • 根据306f在第5步获取的栈信息中查找tid=0x306的线程
  • 定位代码位置(根据打印出来的堆栈信息查看代码所在位置)

注意:从操作系统打印出的虚拟机的本地线程看,本地线程数量和Java线程堆栈中的线程数量相同, 说明二者是一一对应的。只不过java线程中的nid中用16进制来表示, 而本地线程中的id用十进制表示。

DEMO演示

使用虚拟机演示:

使用top命令查看目前操作系统性能情况:

使用idea编写简单的demo进行演示通过进程到线程定位到代码行:

import com.sdgroup.pojo.StudentInfo;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author liwen
 * @Title: PageIndex
 * @Description: 使用命令top-->top -p PID  -- H   jstack pid
 * @date 2019/11/9 / 10:23
 */
@Log4j2
@Controller
public class PageIndexController {


    /**
     * 测试demo
     * @return
     */
    @GetMapping("/7d")
    @ResponseBody
    public Object topDemo() {
        StudentInfo stInfo = new StudentInfo();
        stInfo.setName("topJava");
        stInfo.setAge(30);
        stInfo.setDes("冠礼之年测试java通过top命令查看jvm");
        stInfo.setGrade("7DGroup");

        for (int i = 0; i < 100000; i++) {
            i++;
            try {
                log.info("my is print" + i);
                Thread.sleep(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return stInfo;
    }

    /**
     * 调试
     * @return
     */
    @GetMapping("/7ddemo")
    @ResponseBody
    public Object topDemo1() {
        StudentInfo stInfo = new StudentInfo();
        stInfo.setName("topJava");
        stInfo.setAge(30);
        stInfo.setDes("冠礼之年测试java通过top命令查看jvm");
        stInfo.setGrade("7DGroup");

        return stInfo;
    }
}

打开浏览器访问:

访问写好的请求http://ip:port/7d并且通过工具进行访问,通过查看日志显示系统后台运行,前端一直处于等待状态

可以使用jmeter或者idea等工具进行不断访问显示,方便咱们进行性能定位:

也可以使用idea简单发起请求:

点击请求:

打开linux系统,再次打开窗口中敲top命令查看消耗CPU中的java进程,通过观察该进程在操作系统中消耗cpu不是很高,但是为了演示上面操作步骤,咱们暂时使用该进程进行演示:

使用命令top -p PID即可看到该进程下的线程信息

再次使用:jsack 命令进行,打出dump信息

如果执行没有该命令需要找到jdk安装目录执行:

可以参考:https://www.cnblogs.com/lossingdawn/p/10856199.html

[root@localhost bin]#

[root@localhost bin]# ./jstack 93114 >/home/7d/7djava.dump

[root@localhost bin]#

切换到dump生成的目录下:

可以下载到本地进行查看或者使用jdk自带的jvisualvm工具查看:

目前使用文本查看方式

[root@localhost 7d]# vim 7djava.dump

显示信息

发现该进行消耗多,其实也不多,目前是为演示所以暂时使用下。

转换:十进制转换16进制:

在打开dump文件中通过vim搜索命令查找:

从上面可以看出目前线程正处于TIMED_WAITING状态,表示当前被挂起一段时间,时长为参数中指定的时长,如Thread.sleep(1000)。因此该线程当前不消耗CPU。

找到代码的包名与代码行:

从下面信息得出:

再次查看源码:

总结:

通过压力工具稳定发压,使用原始命令top查看java进程再通过jstack pid>inof.dump命令打出线程信息,通过top -p pid查看线程,通过判断那个线程消耗cpu,再次通过转换为16进制进程定位到代码。

在实际工作中该方法,经常用于线上定位问题,因为线上机器不能安装其他工具,如果是线下测试其实有很多工具可以使用(Jprofiler、jmc、jvisualvm)等工具。

下面简单介绍下线程怎么看:

"http-nio-8080-exec-11" #30 daemon prio=5 os_prio=0 tid=0x00007fadf8001000 nid=0x16bf8 waiting on condition [0x00007fae6c7d0000]

  1. 线程名称:"http-nio-8080-exec-11"
  2. 线程优先级:prio=5
  3. 线程对应的本地线程id号:nid=0x16bf8
  4. 线程的状态:waiting
  5. 线程占用内存地址:[0x00007fae6c7d0000]

光知道上面内容咱们做性能测试还是不知怎么下手?其实咱们通过线程分析知道程序他目前处于什么状态,就知道怎么下手分析,你说呢?。

在分析之前需要了解线程生命周期还得知道谁消耗资源。

线程整个生命周期,可以分为五个阶段,分别是新建状态New、就绪状态Runnable、运行状态Running、阻塞状态Blocked和死亡状态Terminated;

本文分享自微信公众号 - 7DGroup(Zee_7DGroup),作者:李文

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 性能工具之Jmeter小白入门系列之四

    青,取之于蓝,而青于蓝;冰,水为之,而寒于水。木直中绳,輮以为轮,其曲中规。虽有槁暴,不复挺者,輮使之然也。故木受绳则直,金就砺则利,君子博学而日...

    高楼Zee
  • 性能工具之Jmeter常用定时器

    作用:通过ThreadDelay设定每个线程请求之前的等待时间(单位为毫秒)。

    高楼Zee
  • 性能分析之分析决策树1

    高楼Zee
  • 【Java后端面试经历】我和阿里面试官的“又”一次“邂逅”(附问题详解)

    承接上一篇深受好评的文章:《【Java 大厂真实面试经历】我和阿里面试官的一次“邂逅”(附问题详解)》 。时隔 n 个月,又一篇根据读者投稿的《5 面阿里,终获...

    Guide哥
  • Java中的锁原理、锁优化、CAS、AQS

    结论:如果volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。

    Java团长
  • Java多线程Thread VS Runnable详解

    进程是程序在处理机中的一次运行。一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立。所以进程是重量级的任务,它们之...

    Java后端工程师
  • 给大伙来梳理下Java中的各种锁的分类

      大伙在面试的时候应该会经常碰到线程 并发方面的问题,而且也会问到你各种分布式锁的概念,本文就给大家整理了下各种锁的分类,希望对你有所帮助。

    用户4919348
  • .Net线程同步技术解读

    如果代码在多线程环境中运行的结果与单线程运行结果一样,其他变量值也和预期是一样的,那么线程就是安全的;

    心莱科技雪雁
  • Linux下多线程的实现(基于pthread库)

    Linux内核在2.2版本中引入了类似线程的机制。Linux提供的vfork函数可以创建线程,此外Linux还提供了clone来创建一个线程,通过共享原来调用进...

    zy010101
  • C# 温故而知新: 线程篇(三)下

    结果计时器会一直滚动,因为a对象被锁住,除非完成Thread.Sleep(3000000)后才能进入到a共享区 ? 由于以上的问题,微软还是建议我们使用一个私有...

    逸鹏

扫码关注云+社区

领取腾讯云代金券