性能调优

news2024/9/20 15:37:54

性能调优

应用程序在运行过程中经常会出现性能问题,比较常见的性能问题现象是:

  • 通过top命令查看CPU占用率高,接近100甚至多核CPU下超过100都是有可能的。
  • 请求单个服务处理时间特别长,多服务使用skywalking等监控系统来判断是哪一个环节性能低下。
  • 程序启动之后运行正常,但是在运行一段时间之后无法处理任何的请求(内存和GC正常)。

线程转储

线程转储(Thread Dump)提供了对所有运行中的线程当前状态的快照。线程转储可以通过jstack、visualvm等工具获取。其中包含了线程名、优先级、线程ID、线程状态、线程栈信息等等内容,可以用来解决CPU占用率高、死锁等问题

线程转储(Thread Dump)中的几个核心内容:

  • 名称:线程名称,通过给线程设置合适的名称更容易“见名知意”
  • 优先级(prio):线程的优先级
  • Java ID(tid):JVM中线程的唯一ID
  • 本地 ID (nid):操作系统分配给线程的唯一ID
  • 状态:线程的状态,分为: NEW – 新创建的线程,尚未开始执行 RUNNABLE –正在运行或准备执行 BLOCKED – 等待获取监视器锁以进入或重新进入同步块/方法 WAITING – 等待其他线程执行特定操作,没有时间限制 TIMED_WAITING – 等待其他线程在指定时间内执行特定操作 TERMINATED – 已完成执行
  • 栈追踪: 显示整个方法的栈帧信息

线程转储的可视化在线分析平台:https://fastthread.io/ (需要科学上网)

请添加图片描述

CPU占用率高问题的解决方案

1)通过top –c 命令找到CPU占用率高的进程,获取它的进程ID。

2)使用top -p 进程ID单独监控某个进程,按H可以查看到所有的线程以及线程对应 的CPU使用率,找到CPU使用率特别高的线程。

3)使用 jstack 进程ID命令可以查看到所有线程正在执行的栈信息。使用 jstack进程ID > 文件名 保存到文件中方便查看。

4)找到nid线程ID相同的栈信息,需要将之前记录下的十进制线程号转换成16进制 。通过 printf ‘%x\n’ 线程ID 命令直接获得16进制下的线程ID。

请添加图片描述

5)找到栈信息对应的源代码,并分析问题产生原因。

接口响应时间长的问题

已经确定是某个接口性能出现了问题,但是由于方法嵌套比较深,需要借助于arthas定位到具体的方法。

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

命令:trace 类名 方法名

  • 添加 --skipJDKMethod false 参数可以输出JDK核心包中的方法及耗时。
  • 添加 ‘#cost > 毫秒值’ 参数,只会显示耗时超过该毫秒值的调用。
  • 添加 –n 数值 参数,最多显示该数值条数的数据。
  • 所有监控都结束之后,输入stop结束监控,重置arthas增强的对象。

在使用trace定位到性能较低的方法之后,使用watch命令监控该方法,可以获得更为详细的方法信息。

命令: watch 类名 方法名 ‘{params, returnObj}’ ‘#cost>毫秒值' -x 2

  • ‘{params, returnObj}‘ 代表打印参数和返回值。
  • -x 代表打印的结果中如果有嵌套(比如对象里有属性),最多只展开2层。允许设置的最大值为4。

最后记得使用stop命令将所有增强的对象恢复。

JMH

OpenJDK中提供了一款叫JMH(Java Microbenchmark Harness)的工具,可以准确地对Java代码进行基准测试, 量化方法的执行性能。

JMH会首先执行预热过程,确保JIT对代码进行优化之后再进行真正的迭代测试,最后输出测试的结果。

1)引入依赖

<dependencies>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>1.33</version> <!-- 使用最新的版本 -->
    </dependency>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-generator-annprocess</artifactId>
        <version>1.33</version> <!-- 使用最新的版本 -->
    </dependency>
</dependencies>

2)编写测试代码

package cn.ehang;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 3)
@Measurement(iterations = 5)
public class Main {

    String string = "";
    StringBuilder stringBuilder = new StringBuilder();

    @Benchmark
    public String stringAdd() {
        for (int i = 0; i < 1000; i++) {
            string = string + i;
        }
        return string;
    }

    @Benchmark
    public String stringBuilderAppend() {
        for (int i = 0; i < 1000; i++) {
            stringBuilder.append(i);
        }
        return stringBuilder.toString();
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(Main.class.getSimpleName())
                .build();
        new Runner(opt).run();
    }
}

3)测试结果

# JMH version: 1.33
# VM version: JDK 17.0.11, Java HotSpot(TM) 64-Bit Server VM, 17.0.11+7-LTS-207
# VM invoker: C:\Program Files\Java\jdk-17\bin\java.exe
# VM options: -Dvisualvm.id=11302190666600 -javaagent:D:\software\IntelliJ IDEA 2024.1.4\lib\idea_rt.jar=50868:D:\software\IntelliJ IDEA 2024.1.4\bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint (default, use -Djmh.blackhole.autoDetect=true to auto-detect)
# Warmup: 3 iterations, 10 s each
# Measurement: 5 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: cn.ehang.Main.stringAdd

# Run progress: 0.00% complete, ETA 00:02:40
# Fork: 1 of 1
# Warmup Iteration   1: 26.184 ms/op
# Warmup Iteration   2: 60.169 ms/op
# Warmup Iteration   3: 80.841 ms/op
Iteration   1: 103.935 ms/op
Iteration   2: 122.784 ms/op
Iteration   3: 135.320 ms/op
Iteration   4: 147.907 ms/op
Iteration   5: 160.549 ms/op


Result "cn.ehang.Main.stringAdd":
  134.099 ±(99.9%) 84.575 ms/op [Average]
  (min, avg, max) = (103.935, 134.099, 160.549), stdev = 21.964
  CI (99.9%): [49.524, 218.674] (assumes normal distribution)

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

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

相关文章

电子束光刻过程中的场拼接精度

以下内容如有错误&#xff0c;请不吝指教&#xff0c;感谢&#xff01; 1、EBL为什么会出现场拼接误差&#xff0c;如何解决&#xff1f; ChatGPT 说&#xff1a; 在电子束光刻&#xff08;EBL&#xff09;过程中&#xff0c;SOI&#xff08;硅绝缘体&#xff09;芯片上出现*…

计算机毕业论文题目:设计与实现一个校园通知信息系统

设计与实现一个校园通知信息系统是一个涉及多个方面的复杂项目&#xff0c;它旨在提高信息传递的效率和准确性&#xff0c;确保学生、教师以及学校管理人员能够及时获取到重要的通知信息。以下是关于如何设计并实现这样一个系统的详细说明&#xff1a; 1. 需求分析 用户…

【高中数学/不等式/数学归纳法/等比数列】证明伯努利不等式(1+h)^n>1+nh的三种方式

【伯努利不等式】 (1h)^n>1nh &#xff08;h>0,n为大于1的自然数&#xff09; 【数学归纳法证法】 证明&#xff1a; n2时&#xff0c;(1h)^212hh^2>12h 不等式成立 n3时&#xff0c;(1h)^313h3h^2h^3>13h 不等式成立 假设nk时&#xff0c;有(1h)^k>…

机房三大网络拓扑图,太实用了

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 下午好&#xff0c;我的网工朋友。 通常来说&#xff0c;机房的三大网络拓扑图指的是星型拓扑、总线型拓扑和环形拓扑。 在实际的机房网络设计中…

vue项目加载cdn失败解决方法

注释index.html文件中 找到vue.config.js文件注释、

MySQL_图形管理工具简介、下载及安装(超详细)

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

【VUE3.0】动手做一套像素风的前端UI组件库---先导篇

系列文章目录 【VUE3.0】动手做一套像素风的前端UI组件库—Button 目录 系列文章目录引言准备素材字体鼠标手势图 创建vue3项目构建项目1. 根据命令行提示选择如下&#xff1a;2. 进入项目根目录下载依赖并启动。3. 设置项目src路径别名&#xff0c;方便后期应用路径。4. 将素…

Debian 12上安装google chrome

当前系统&#xff1a;Debian 12.7 昨天在Debian 12.7上安装Google Chrome时&#xff0c;可能由于网络原因&#xff0c;导入公钥始终失败。 导致无法正常使用命令#apt install google-chrome-stable来安装google chrome; 解决办法&#xff1a; Step1.下载当前google chrome稳…

C++性能优化-代码角度

减少跳转/分支语句和函数调用 原因 分支语句&#xff1a;当 CPU 执行到分支语句时&#xff0c;将会进行分支预测&#xff08;对大部分PC&#xff09;。如果分支预测错误&#xff0c;就会清空已经预取和执行的部分指令&#xff0c;重新从正确的分支开始取指和执行&#xff0c;…

某东-h5st参数逆向分析

目标&#xff1a;商品搜索翻页接口 直接搜索h5st就可以搜到&#xff0c;所有可疑位置都打上断点&#xff0c;然后翻页&#xff0c;最终断点位置&#xff1a; window.PSign.sign(colorParamSign)是异步代码&#xff0c;colorParamSign是传入的参数&#xff0c;执行后把包含h5st…

基于YOLOv5的教室人数检测统计系统

基于YOLOv5的教室人数检测统计系统可以有效地用于监控教室内的学生数量&#xff0c;适用于多种应用场景&#xff0c;比如 自动考勤、安全监控或空间利用分析 以下是如何构建这样一个系统的概述&#xff0c;包括环境准备、数据集创建、模型训练以及如何处理不同类型的媒体输入…

【机器学习】--- 序列建模与变分自编码器(VAE)

在机器学习领域&#xff0c;序列建模与变分自编码器&#xff08;Variational Autoencoder, VAE&#xff09; 是两个至关重要的技术&#xff0c;它们在处理时间依赖性数据与复杂数据生成任务中都发挥着关键作用。序列建模通常用于自然语言处理、语音识别等需要保持顺序关系的任务…

【老板必看!】电脑怎么看使用软件时间记录?一文读懂5种超实用的方法!

在企业管理中&#xff0c;电脑虽不善言语、不会说话&#xff0c;但会留下无数线索&#xff0c;就像一场未解之谜&#xff0c;等待着各位福尔摩斯得到来&#xff0c;去揭开它的秘密面纱。 你是否曾好奇过&#xff0c;当你不在的时候&#xff0c;员工都在用电脑都在忙些什么&…

基于python+django+vue的影视推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的影…

大表数据如何在OceanBase中进行表分区管理的实践

背景 将Zabbix的数据库迁移至OceanBase后&#xff0c;以其中的几个大表作为案例&#xff0c;本文将分享如何利用ODC&#xff08;OceanBase 开发者工具&#xff09;&#xff0c;来进行自动管理OB数据库中的表分区的方案。 因为原始表里已经有大量的数据&#xff0c;如果贸然对…

快速掌握Postman接口测试

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、前言 在前后端分离开发时&#xff0c;后端工作人员完成系统接口开发后&#xff0c;需要与前端人员对接&#xff0c;测试调试接口&#xff0c;验证接口的正…

【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL16

使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器 描述 ②请使用2片该优先编码器Ⅰ及必要的逻辑电路实现16线-4线优先编码器。优先编码器Ⅰ的真值表和代码已给出。 可将优先编码器Ⅰ的代码添加到本题答案中&#xff0c;并例化。 优先编码器Ⅰ的代码如下&#xff1a; module…

BERT模型解读与简单任务实现(论文复现)

BERT模型解读与简单任务实现&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 概述 相关背景 语言模型&#xff1a;语言模型是指对于任意的词序列&#xff0c;它能够计算出这个序列是一句话的概率。 预训练&#xff1a;预训练是一种迁移学习的概念…

c++类和对象(6个默认成员函数)第二级中阶

目录 6个默认成员函数介绍 构造函数 构造函数是什么&#xff1f; 构造函数的6种特性 析构函数 析构函数是什么&#xff1f; 析构函数的特性 拷贝构造函数 什么是拷贝构造函数 拷贝函数的特性 四.默认生成的拷贝构造实行的是浅拷贝&#xff08;值拷贝&#xff09;&am…

【2024】前端学习笔记9-内部样式表-外部导入样式表-类选择器

学习笔记 内部样式表外部导入样式表类选择器&#xff1a;class 内部样式表 内部样式表是将 CSS 样式规则写在 HTML 文档内部。通过<style>标签在 HTML 文件的<head>部分定义样式。 简单示例&#xff1a; <!DOCTYPE html><html><head><style…