CPU、内存占用率高排查

CPU高占用

排查思路
  1. top 命令查看CPU占用率高的进程
  2. top -H -p ${pid} 命令查看具体是进程的哪个线程占用CPU
  3. printf ‘%x\n’ ${pid} 将线程的pid转为16进制
  4. jstack ${十六进制pid} | grep -A 20 查看线程的基本信息与方法调用栈
模拟排查
[root@VM-24-5-centos www]# top
top - 15:39:55 up 69 days, 13:43,  2 users,  load average: 3.10, 1.75, 0.93
Tasks: 110 total,   1 running, 109 sleeping,   0 stopped,   0 zombie
%Cpu(s): 50.5 us,  0.5 sy,  0.0 ni, 49.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1881840 total,   100232 free,   829564 used,   952044 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   862992 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
27145 root      20   0 2750780  23504  11488 S  99.7  1.2   1:33.06 java
 6493 root      20   0 1033692  51588  16660 S   0.3  2.7 121:18.66 YDService
13842 root      20   0  680292  14520   2464 S   0.3  0.8  10:39.63 barad_agent

PID为27145的java进程占用CPU较多

[root@VM-24-5-centos www]# top -H -p 27145
top - 15:41:10 up 69 days, 13:44,  2 users,  load average: 1.60, 1.58, 0.93
Threads:  13 total,   1 running,  12 sleeping,   0 stopped,   0 zombie
%Cpu(s): 50.3 us,  0.2 sy,  0.0 ni, 49.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1881840 total,   103628 free,   826112 used,   952100 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   866456 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
27157 root      20   0 2750780  23504  11488 R 99.7  1.2   2:47.67 java
27145 root      20   0 2750780  23504  11488 S  0.0  1.2   0:00.00 java
27146 root      20   0 2750780  23504  11488 S  0.0  1.2   0:00.10 java

PID为27145的java进程的PID为27157的子线程占用CPU较多

[root@VM-24-5-centos www]# jstack 27145 | grep 0x6a15 -A 20
"Business Thread" #8 prio=5 os_prio=0 tid=0x00007f545c102000 nid=0x6a15 runnable [0x00007f544c6f5000]
   java.lang.Thread.State: RUNNABLE
	at CPUOccupancyRateTest.lambda$businessThread$0(CPUOccupancyRateTest.java:10)
	at CPUOccupancyRateTest$$Lambda$1/834600351.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f545c0b9000 nid=0x6a13 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f545c0b6000 nid=0x6a12 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f545c0b3000 nid=0x6a11 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f545c0b1800 nid=0x6a10 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f545c07e800 nid=0x6a0f in Object.wait() [0x00007f544ccfb000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
[root@VM-24-5-centos www]#

将线程的PID转为16进制后,通过jstack该线程的信息与方法调用栈,该线程的名称为: Business Thread,可定位到执行代码:CPUOccupancyRateTest.java:10。看下具体java代码:

public class CPUOccupancyRateTest {

    public static void main(String[] args) {
        businessThread();
    }

    static void businessThread() {
        Thread thread = new Thread(() -> {
            while (true) {  // line 10
                // Do nothing
            }
        });
        thread.setName("Business Thread");
        thread.start();
    }
}

内存高占用(使用MAT分析)

排查思路

若仍未发生OOM:

  1. top 命令查看Memeory占用率高的java进程
  2. jmap dump java进程的内存快照文件
  3. 通过可视化分析工具导入快照文件进行排查
    3.1. 占用内存过多的对象是哪些
    3.2. 这些对象被谁引用
    3.3. 定位到具体代码

注:若堆内存很大时,直接在线上服务器执行 jmap dump 内存快照文件,会导致长时间STW来导出很大的快照文件,引发服务程序不可用。

若发生了OOM,通过配置的JVM启动参数:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=${path}

找到快照文件,导入到可视化分析工具中分析。

OOM模拟排查

JVM启动参数

-Xmx10m -Xms10m 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/Users/congqingquan/Desktop

测试代码

public class OOMTest {

    public static void main(String[] args) {
        oomTest();
    }

    static void oomTest() {
        Thread thread = new Thread(() -> {
            List<Person> list = new ArrayList<>();
            while (true) {
                list.add(new Person());
            }
        });

        thread.setName("OOM Test Thread");
        thread.start();
    }

    static class Person {}
}
使用MAT引入快照文件进行分析

MAT下载地址,红、黄框为常用的分析功能

在这里插入图片描述

Histogram

类的实例对象的柱状统计分析图

在这里插入图片描述

默认以Byte为单位展示数据,若需要更改显示单位可以在:
Preferences -> Memory Analyzer -> Bytes Display 中选择,一般使用Smart选项。

字段解释:

  1. Objects:实例对象的数量
  2. Shallow Heap:实例对象占用的内存大小(仅单纯的将每个实例的大小相加汇总)
  3. Retained Heap:实例对象若都可以被回收,那么可以被GC释放的内存大小(不仅需要考虑每个实例本身的大小,也会计算实例成员属性指向的实例的大小)
Dominator_tree

在这里插入图片描述

Dominator Tree(支配树)视图,列出了每个对象实例的引用关系的树状图,包含了占用内存的大小和百分比。

字段解释:

  1. Shallow Heap:实例对象占用的内存大小(仅单纯的将每个实例的大小相加汇总)
  2. Retained Heap:实例对象若都可以被回收,那么可以被GC释放的内存大小(不仅需要考虑每个实例本身的大小,也会计算实例成员属性指向的实例的大小)
  3. Percentage:占用堆内存的百分比
Thread_overview

在这里插入图片描述

线程概述:程序中所有的线程的信息,如:方法调用栈,方法的栈帧,每个线程、方法中创建的对象以及占用堆内存大小。

字段解释:

  1. Name:线程名称
  2. Shallow Heap:实例对象占用的内存大小(仅单纯的将每个实例的大小相加汇总)
  3. Retained Heap:实例对象若都可以被回收,那么可以被GC释放的内存大小(不仅需要考虑每个实例本身的大小,也会计算实例成员属性指向的实例的大小)
  4. Context Class Loader:上下文类加载器
  5. Is Daemon:是否为守护线程
回顾排查思路中的第三步,使用排查工具分析:
  1. 占用内存过多的对象是哪些?Histogram,可以直观的看到统计数据
  2. 这些对象被谁引用?Dominator_tree,从根对象角度,根据Retained Heap排序,查看哪个GC Root对象的引用关系树中存在的对象占用内存过大
  3. 定位到具体代码?Thread_overview,从线程角度,根据Retained Heap排序,查看哪个线程生成的对象占用内存过多,分布在线程的哪些方法中。

由于案例比较简单,通过MAT常用功能的讲解,已经可以在解释截图中看到问题根源了:

  1. Histogram 视图说明了占用内存过多的对象:Person。
  2. Thread_overview 视图说明了这些对象主要集中在OOM Test Thread线程中。通过线程的方法调用栈,可以看到问题出在oomTest方法上,因为方法内的某个lambda表达式中的一个局部变量ArrayList对象存储了大量的数据。截图中我并没有展开,里面存储的正是大量的Person实例。
Leak Suspects

在这里插入图片描述

泄漏疑点:MAT会根据快照文件帮助你分析,并列出分析后的可疑点。点击Detail有更具体的详细说明,非常好用~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SQL Server CPU占用率可能是由于以下原因导致的: 1. 查询语句效率低下:如果查询语句没有优化,可能会导致CPU占用率。可以通过优化查询语句来减少CPU占用率。 2. 索引问题:如果表没有正确的索引,可能会导致查询效率低下,从而导致CPU占用率。可以通过创建正确的索引来解决这个问题。 3. 内存不足:如果SQL Server使用的内存不足,可能会导致CPU占用率。可以通过增加内存来解决这个问题。 4. 并发连接数过:如果SQL Server同时处理的连接数过多,可能会导致CPU占用率。可以通过限制并发连接数来解决这个问题。 5. SQL Server版本过低:如果SQL Server版本过低,可能会导致CPU占用率。可以升级到最新版本来解决这个问题。 以上是一些可能导致SQL Server CPU占用率的原因,需要根据具体情况进行排查和解决。 ### 回答2: SQL Server CPU占用率可能由许多原因引起,以下是一些可能的原因和解决方法: 1.查询导致CPU资源瓶颈。在查询中使用了较多的函数或在大型表上使用了JOIN操作,并且查询过程中无法利用索引,都可能导致CPU占用率。解决可以优化查询或对表或相关的视图索引建立相关索引,或采用分区方式等来规避一些性能问题。 2.其他应用程序占用导致SQL Server CPU资源不足。系统资源是有限的,如果有其他应用程序同时占用CPU资源,就会导致SQL Server CPU占用率。解决可以在服务器上安装该应用程序的其他实例,并对SQL Server分配更多的硬件资源。 3.SQL Server配置不当。如果SQL Server安装或配置存在问题,比如不存在足够的物理内存,或者内存不足以满足SQL Server的运行要求,这些都会导致CPU占用率。解决可以升级服务器,重视资料维护及其优化,调整配置。 4.SQL Server脚本问题。如果有过于复杂的SQL脚本,则需要运行一定时间,可能会占用很多CPU资源。解决办法可以使用合适的存储过程等,降低脚本执行时间。 5.SQL Server日志过多。由于SQL Server写入大量数据到日志文件中,可能也会导致CPU占用率。使用压缩、切换和削减日志文件轮换等方式,可以减少日志过多的问题,达到更好的性能。 以上是SQL Server占用率的一些原因和解决方法,如果遇到问题,可以根据具体情况采取相应的解决方案。 ### 回答3: SQL Server 的 CPU 占用率,可能是由于以下原因引起的: 1. 查询负载过重:当大量的查询同时请求 SQL Server 时,它的 CPU 占用率就会升,因为 SQL Server 必须尽快处理这些请求。如果您的应用程序中有许多查询,建议优化它们或者使用索引来加快查询速度。 2. 锁竞争:当多个用户尝试同时访问同一个资源(例如表或行)时,可能会导致锁竞争,从而增加 CPU 占用率。在这种情况下,可以尝试优化查询,或者考虑重新设计应用程序以避免锁竞争。 3. 资源争抢:如果您的 SQL Server 实例与其他应用程序或服务共享 CPU内存或其他资源,那么当这些应用程序或服务需要更多资源时,它们会减少 SQL Server 实例可用的资源,从而增加 CPU 占用率。在这种情况下,可以考虑增加硬件资源,或者将 SQL Server 实例迁移到专用服务器上。 4. 内存不足:当 SQL Server 实例没有足够的内存可用时,它会不断进行磁盘读取和写入,从而加重 CPU 的负担。在这种情况下,可以尝试增加可用内存,或者设置最小内存限制,以防止其他进程占用过多内存。 5. 过度使用临时表:如果查询中使用了大量临时表,那么会增加 CPU 占用率。尝试减少使用临时表或者优化查询可以减少 CPU 占用率。 解决 SQL Server 的 CPU 占用率的问题,可以使用如下方法: 1. 监视性能计数器和 sys.dm_os_performance_counters 视图,以确定哪些进程或操作正在消耗 CPU 时间,以及需要采取哪些措施来减少此类操作的负载。 2. 使用 SQL Server Profiler 或 Extended Events 跟踪查询,以查找可能导致 CPU 占用率的查询。 3. 优化查询,使用索引等方法来提查询性能,减少 CPU 占用率。 4. 增加可用内存,以减少磁盘读写操作的频率。 5. 将 SQL Server 实例迁移到专用服务器上,避免和其他应用程序或服务共享 CPU内存等资源。 总之,Sql Server 的 CPU 占用率,需要综合考虑各种因素,从查询负载、锁竞争、资源争抢、内存不足、临时表使用等方面综合优化才能有效解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值