JVM实战之性能调优[2](线程转储案例认识和分析)

文章目录

  • 版权声明
  • 案例1:CPU占用率高问题
    • 问题描述
    • 解决思路
    • 补充内容
  • 案例2:接口响应时间长问题
    • 问题描述
    • 解决思路
    • Arthas trace命令
    • Arthas watch命令
    • 解决问题
  • 案例3:定位偏底层性能问题
    • 问题描述
    • 解决思路:Arthas火焰图
    • 问题解决
  • 案例4:线程被耗尽问题
    • 问题描述
    • 解决思路
    • 问题解决
    • 死锁代码优化

版权声明

  • 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明,所有版权属于黑马程序员或相关权利人所有。本博客的目的仅为个人学习和交流之用,并非商业用途。
  • 我在整理学习笔记的过程中尽力确保准确性,但无法保证内容的完整性和时效性。本博客的内容可能会随着时间的推移而过时或需要更新。
  • 若您是黑马程序员或相关权利人,如有任何侵犯版权的地方,请您及时联系我,我将立即予以删除或进行必要的修改。
  • 对于其他读者,请在阅读本博客内容时保持遵守相关法律法规和道德准则,谨慎参考,并自行承担因此产生的风险和责任。
  • 本博客中的部分观点和意见仅代表我个人,不代表黑马程序员的立场。
  • 由于作者精力有限,有关代码的演示和工具的使用和操作,请食用官方的B站JVM教程视频

案例1:CPU占用率高问题

问题描述

  • 监控人员通过prometheus的告警发现CPU占用率一直处于很高的情况,通过top命令看到是由于Java程序引起的,希望能快速定位导致性能问题的代码。

解决思路

  1. 通过top –c 命令找到CPU占用率高的进程,获取进程ID
    在这里插入图片描述
  2. 使用top -p 进程ID单独监控某个进程,按 H H H查看到所有的线程以及线程对应的CPU使用率,找到CPU使用率特别高的线程,并记录线程ID。
    在这里插入图片描述
  3. 使用 jstack 进程ID 命令可以查看到所有线程正在执行的栈信息。使用 jstack 进程ID > 文件名 保存到文件中方便查看。
    在这里插入图片描述
  4. 找到 n i d 线程 I D nid线程ID nid线程ID相同的栈信息,需要将之前记录下的十进制线程号转换成16进制。通过 p r i n t f ′ printf '%x\n' printf 线程ID 命令直接获得16进制下的线程ID
    在这里插入图片描述
  5. 找到栈信息对应的源代码,并分析问题产生原因

补充内容

  • 在定位CPU占用率高的问题时,需要关注的是状态为 R U N N A B L E RUNNABLE RUNNABLE的线程。但实际上,有一些线程执行本地方法时并不会消耗CPU,而只是在等待。但 JVM 仍然会将它们标识成“RUNNABLE”状态。
    在这里插入图片描述

案例2:接口响应时间长问题

问题描述

  • 程序运行过程中,发现有几个接口的响应时间特别长,需要快速定位执行过程中出现性能问题的代码。

解决思路

  • 确定出现性能问题的方法,借助于arthas定位到具体的方法(在方法嵌套比较深的情况下)
    在这里插入图片描述

Arthas trace命令

  • 使用arthas的trace命令,可以展示出整个方法的调用路径以及每一个方法的执行耗时。
  • 语法格式
    trace 类名 方法名
    

⚫ 添加--skipJDKMethod false 参数可以输出JDK核心包中的方法及耗时。
⚫ 添加 #cost > 毫秒值 参数,只会显示耗时超过该毫秒值的调用。
⚫ 添加 –n 数值 参数,最多显示该数值条数的数据。
⚫ 所有监控都结束之后,输入 s t o p stop stop结束监控,重置arthas增强的对象
在这里插入图片描述

Arthas watch命令

  • 使用trace定位到性能较低的方法后,使用watch命令监控该方法,可以获得更为详细的方法信息。
  • 语法格式
    watch 类名 方法名 ‘{params, returnObj}’ ‘#cost>毫秒值' -x 2
    
  • {params, returnObj} 代表打印参数和返回值。
  • -x 代表打印的结果中如果有嵌套(比如对象里有属性),最多只展开2层。允许设置的最大值为4。
    在这里插入图片描述

解决问题

  1. 通过arthas的trace命令,首先找到性能较差的具体方法,如果访问量比较大,建议设置最小的耗时,精确的找到耗时比较高的调用。
  2. 通过watch命令,查看此调用的参数和返回值,关注参数,在开发环境或者测试环境模拟现象,通过debug找到具体的问题根源。
  3. 使用stop命令将所有增强的对象恢复。

案例3:定位偏底层性能问题

问题描述

  • 接口中使用for循环向ArrayList中添加数据,但是最终发现执行时间比较长,需要定位是导致的性能低下的原因
@GetMapping("/profile1")
public void test6() throws InterruptedException {ArrayList<Integer> objects = new ArrayList<>();for (Integer i = 0; i < 20000000; i++) {objects.add(i);}
}

解决思路:Arthas火焰图

  • 使用Arthas提供性能火焰图的功能,查看方法的执行耗时
  • 使用arthas的profile命令,生成性能监控的火焰图
    profiler start #1 开始监控方法执行性能
    profiler stop --format html #2 以HTML的方式生成火焰图
    
  • 火焰图中一般找绿色部分Java中栈顶上比较平的部分,很可能就是性能的瓶颈
    在这里插入图片描述
  • 偏底层的性能问题,特别是由于JDK中某些方法被大量调用导致的性能低下,可以使用火焰图非常直观的找到原因

问题解决

  • 案例中是由于创建ArrayList时没有手动指定容量,导致使用默认的容量而在添加对象过程中发生了多次的扩容,扩容需要将原来数组中的元素复制到新的数组中,消耗了大量的时间。
  • 优化后的代码
@GetMapping("/profile2")public void test7() throws InterruptedException {ArrayList<Integer> objects = new ArrayList<>(20000000);for (Integer i = 0; i < 20000000; i++) {objects.add(i);}}

案例4:线程被耗尽问题

问题描述

  • 程序在启动运行一段时间之后,就无法接受任何请求。将程序重启之后继续运行,依然会出现相同的情况。

解决思路

  • 线程耗尽问题,一般是由于执行时间过长,分析方法分成两步:
    1. 检测是否有死锁产生,无法自动解除的死锁会将线程永远阻塞。
    2. 如果没有死锁,再使用案例1的打印线程栈的方法检测线程正在执行的方法,一般大量出现的方法就是慢方法。
  • 死锁:两个或以上的线程因为争夺资源而造成互相等待的现象

问题解决

线程死锁可以通过三种方法定位问题:

  1. jstack -l 进程ID > 文件名将线程栈保存到本地,在文件中搜索deadlock即可找到死锁位置
    在这里插入图片描述
  2. 开发环境中使用visual vm或者Jconsole工具,检测死锁。使用线程快照生成工具查看死锁的根源。生产环境的服务一般不会允许使用这两种工具连接。
    在这里插入图片描述
  3. 使用fastthread自动检测线程问题(Fastthread,是一款在线的AI自动线程问题检测工具,可以提供线程分析报告。通过报告查看是否存在死锁问题。)
    在这里插入图片描述

死锁代码优化

  • 问题代码
private Object obj1 = new Object();
private Object obj2 = new Object();
@GetMapping("/deadlock1")
public String test1() throws InterruptedException {synchronized (obj1){Thread.sleep(5000);synchronized (obj2){return "返回成功";}}
@GetMapping("/deadlock2")
public String test2() throws InterruptedException {synchronized (obj2){Thread.sleep(5000);synchronized (obj1){return "返回成功";}}    
  • 优化代码
private Object obj1 = new Object();
private Object obj2 = new Object();
private Lock lock1 = new ReentrantLock();
private Lock lock2 = new ReentrantLock();@GetMapping("/deadlock1")
public String test1() throws InterruptedException {boolean b1 = lock1.tryLock(1, TimeUnit.SECONDS);if(b1){try {Thread.sleep(5000);boolean b2 = lock2.tryLock(1, TimeUnit.SECONDS);if(b2){try{return "返回成功";}finally {lock2.unlock();}}}finally {lock1.unlock();}}return "处理失败";
}@GetMapping("/deadlock2")
public String test2() throws InterruptedException {boolean b1 = lock2.tryLock(1, TimeUnit.SECONDS);if(b1){try {Thread.sleep(5000);boolean b2 = lock1.tryLock(1, TimeUnit.SECONDS);if(b2){try{return "返回成功";}finally {lock1.unlock();}}}finally {lock2.unlock();}}return "处理失败";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2904914.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【VMware Workstation】公司所有主机和虚拟机ip互通,以及虚拟机目录迁移

文章目录 1、场景2、环境3、实战3.1、所有主机和虚拟机ip互通Stage 1 : 【虚拟机】设置为桥接模式Stage 2 : 【虚拟机】设置ipStage 3 : 【路由器】ARP 静态绑定MACStage 3-1 ping 路由器 ipStage 3-2 【静态绑定】虚拟机查看mac地址Stage 3-3 【静态绑定】路由器ARP 静态绑定 …

LLM之RAG实战(三十五)| 使用LangChain的3种query扩展来优化RAG

RAG有时无法从矢量数据库中检索到正确的文档。比如我们问如下问题&#xff1a; 从1980年到1990年&#xff0c;国际象棋的规则是什么&#xff1f; RAG在矢量数据库中进行相似性搜索&#xff0c;来查询与国际象棋规则问题相关的相关文档。然而&#xff0c;在某些情况下&#xff0…

论文《Exploring to Prompt for Vision-Language Models》阅读

论文《Exploring to Prompt for Vision-Language Models》阅读 论文概况论文动机&#xff08;Intro&#xff09;MethodologyPreliminaryCoOp[CLASS]位置Context 是否跨 class 共享表示和训练 ExperimentsOverall ComparisonDomain GeneralizationContext Length (M) 和 backbon…

Gitlab CI---could not read username for xxx: no such device or address

0 Preface/Foreword 项目开发中&#xff0c;经常会使用第三方的算法或者功能&#xff0c;那么就需要把对应的repo以子模块的方式添加到当前repo中。 添加命令&#xff1a; git submodule add <URL> 1 问题表现 子模块添加成功&#xff0c;但是GitLab CI阶段&#xff…

蓝桥杯 - 小明的背包3(多重背包)

解题思路&#xff1a; 动态规划 多重背包问题需要在01背包问题&#xff08;不重复&#xff09;的基础上多加一层循环进行遍历&#xff0c;并且dp[ j ]的式子也需要修改 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan …

2024/03/28(C++·day4)

一、思维导图 二、练习题 1、写出三种构造函数&#xff0c;算术运算符、关系运算符、逻辑运算符重载尝试实现自增、自减运算符的重载 #include <iostream>using namespace std;// 构造函数示例 class MyClass { private:int data; public:// 默认构造函数MyClass() {da…

Java与Go:字符串转IP

在本文中&#xff0c;我们将了解如何将简单的对比Java和Go是如何将字符串解析为IP地址。 Java 在Java中&#xff0c;将字符串转换为IP地址最无脑的一个方法&#xff1a; import java.net.InetAddress; import java.net.UnknownHostException;public class Main {public stat…

OpenHarmony实战开发-使用ArkTS语言实现简易视频播放器

介绍 本篇Codelab使用ArkTS语言实现视频播放器&#xff0c;主要包括主界面和视频播放界面&#xff0c;我们将一起完成以下功能&#xff1a; 主界面顶部使用Swiper组件实现视频海报轮播。主界面下方使用List组件实现视频列表。播放界面使用Video组件实现视频播放。在不使用视频…

RTOS线程切换的过程和原理

0 前言 RTOS中最重要的一个概念就是线程&#xff0c;线程的按需切换能够满足RTOS的实时性要求&#xff0c;同时能将复杂的需求分解成一个个线程执行减轻我们开发负担。 本文从栈的角度出发&#xff0c;详细介绍RTOS线程切换的过程和原理。 注&#xff1a;本文参考的RTOS是RT-T…

腾讯云邮件推送功能有哪些?如何有效使用?

腾讯云邮件推送如何设置&#xff1f;怎么用邮件推送做高效营销&#xff1f; 腾讯云作为业界领先的云服务提供商&#xff0c;其邮件推送功能在便捷性、稳定性和安全性上都有着出色的表现。那么&#xff0c;腾讯云邮件推送功能究竟有哪些呢&#xff1f;让AokSend来探个究竟。 腾…

Vite 为什么比 Webpack 快?

目录 1. Webpack 的构建原理 2. Script 的模块化&#xff08;主流浏览器对 ES Modules 的支持&#xff09; 3. Webpack vs Vite 开发模式的差异 对 ES Modules 的支持 底层语言的差异 热更新的处理 1. Webpack 的构建原理 前端之所以需要类似于 Webpack 这样的构建工具&…

windows@系统信息查看若干方法@查看硬件信息@系统信息仪表盘@资源占用OSD悬浮窗口

文章目录 操作系统简要信息查看&#x1f47a;计算机软硬件信息查看windows自带工具msinfo32dxdiagcompmgmtsettingssysteminfo.exe 其他专业软件查看计算机软硬件信息&#x1f47a;OSD系统仪表盘系列软件TrafficMonitor插件功能 Rainmeter时间更改板块刷新显示和关闭 Rainmeter…

实现DevOps需要什么?

实现DevOps需要什么&#xff1f; 硬性要求&#xff1a;工具上的准备 上文提到了工具链的打通&#xff0c;那么工具自然就需要做好准备。现将工具类型及对应的不完全列举整理如下&#xff1a; 代码管理&#xff08;SCM&#xff09;&#xff1a;GitHub、GitLab、BitBucket、SubV…

flutter 修改app名字和图标

一、修改名字 在Android中修改应用程序名称&#xff1a; 在AndroidManifest.xml文件中修改应用程序名称&#xff1a; 打开Flutter项目中的android/app/src/main/AndroidManifest.xml文件。找到<application>标签&#xff0c;然后在android:label属性中修改应用程序的名称…

Xcode删除原本的Git,再添加新的git

本文参考&#xff1a;Xcode怎么删除原本git,在重新设置新的git地址_ios xcode 删除原本git-CSDN博客 开发中会有一个问题。Xcode项目A 提交到Git服务器server1&#xff0c;此时项目A内部已经存在一个Git文件&#xff0c;与server1相关联。 此时你想将项目A提交到 另一个Git…

【InternLM 实战营第二期笔记】书生·浦语大模型全链路开源体系及InternLM2技术报告笔记

大模型 大模型成为发展通用人工智能的重要途径 专用模型&#xff1a;针对特定任务&#xff0c;一个模型解决一个问题 通用大模型&#xff1a;一个模型应对多种任务、多种模态 书生浦语大模型开源历程 2023.6.7&#xff1a;InternLM千亿参数语言大模型发布 2023.7.6&#…

Python拆分PDF、Python合并PDF

WPS能拆分合并&#xff0c;但却是要输入编辑密码&#xff0c;我没有。故写了个脚本来做拆分&#xff0c;顺便附上合并的代码。 代码如下&#xff08;extract.py) #!/usr/bin/env python """PDF拆分脚本(需要Python3.10)Usage::$ python extract.py <pdf-fil…

Linux用户及用户组权限

一、用户和用户组 功能项命令实例作用用户组cat /etc/group查看当前系统存在的用户组groupadd testing添加一个新的用户组testingcat /etc/group查看组是否被新增成功groupmod -n test testing将testing重命名成testgroupdel test删除组testgroups root查看用户root所在的所有…

原型链-(前端面试 2024 版)

来讲一讲原型链 原型链只存在于函数之中 四个规则 1、引用类型&#xff0c;都具有对象特性&#xff0c;即可自由扩展属性。 2、引用类型&#xff0c;都有一个隐式原型 __proto__ 属性&#xff0c;属性值是一个普通的对象。 3、引用类型&#xff0c;隐式原型 __proto__ 的属…

基于单片机小型家用燃气锅炉控制系统设计

**单片机设计介绍&#xff0c;基于单片机小型家用燃气锅炉控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的小型家用燃气锅炉控制系统设计&#xff0c;主要目标是实现锅炉的智能化控制&#xff0c;包括温…