首页 > 其他分享 > CPU 爆高【1】

CPU 爆高【1】

时间:2022-10-24 00:55:37浏览次数:41  
标签:00 1995 05 爆高 xxx GC CPU 79

CPU 真的爆高吗?

要确认是否真的爆高,可以使用 !tp 观察。即 !threadpool

0:000> !tp
CPU utilization: 96%
Worker Thread: Total: 36 Running: 36 Idle: 0 MaxLimit: 32767 MinLimit: 16
Work Request in Queue: 61
    Unknown Function: 00007ffc5c461750  Context: 00000187da7a9788
    Unknown Function: 00007ffc5c461750  Context: 0000017fcdd36e88
    ...
    Unknown Function: 00007ffc5c461750  Context: 00000187da5e87d8
    Unknown Function: 00007ffc5c461750  Context: 00000187da872788
--------------------------------------
Number of Timers: 2
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 32 CurrentLimit: 1 MaxLimit: 1000 MinLimit: 16

从卦中可以看到 CPU=96%,果然是 CPU 爆高,而且 Work Request 也累积了 61 个任务未处理,看样子下游不给力哈? 不给力有可能是因为 GC 触发导致线程频繁停顿,也可能真的是处理太慢。

是 GC 触发了吗?

要查看是否真的 GC 触发,可以用 !t -special 观察下是否有 SuspendEE 字样

0:000> !t -special
ThreadCount:      83
UnstartedThread:  0
BackgroundThread: 74
PendingThread:    0
DeadThread:       9
Hosted Runtime:   no
                                                                                                        Lock  
       ID OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
  19    1 1c84 0000017abe10cf60    28220 Preemptive  0000000000000000:0000000000000000 0000017abe103f70 0     Ukn 
  ...
          OSID Special thread type
       26 1c78 DbgHelper 
       27 1328 GC SuspendEE 
       28 1e78 GC 
       29 1ffc GC 
       30 1de0 GC 

果不其然 27 号线程带了 SuspendEE ,说明当前 GC 是触发状态,接下来看下 27 号线程的非托管栈, 到底发生了什么。

0:027> k
 # Child-SP          RetAddr               Call Site
00 00000074`11aff348 00007ffc`66624abf     ntdll!NtWaitForSingleObject+0x14
01 00000074`11aff350 00007ffc`591aa747     KERNELBASE!WaitForSingleObjectEx+0x8f
02 00000074`11aff3f0 00007ffc`591aa6ff     clr!CLREventWaitHelper2+0x3c
03 00000074`11aff430 00007ffc`591aa67c     clr!CLREventWaitHelper+0x1f
04 00000074`11aff490 00007ffc`59048ef5     clr!CLREventBase::WaitEx+0x7c
05 00000074`11aff520 00007ffc`5905370e     clr!SVR::t_join::join+0x10f
06 00000074`11aff580 00007ffc`59049278     clr!SVR::gc_heap::plan_phase+0x11f4
07 00000074`11aff900 00007ffc`590494d6     clr!SVR::gc_heap::gc1+0xb8
08 00000074`11aff950 00007ffc`59048c64     clr!SVR::gc_heap::garbage_collect+0x870
09 00000074`11aff9f0 00007ffc`59192487     clr!SVR::gc_heap::gc_thread_function+0x74
0a 00000074`11affa20 00007ffc`59194194     clr!SVR::gc_heap::gc_thread_stub+0x7e
0b 00000074`11affa60 00007ffc`694184d4     clr!GCThreadStub+0x24
0c 00000074`11affa90 00007ffc`69dee8b1     kernel32!BaseThreadInitThunk+0x14
0d 00000074`11affac0 00000000`00000000     ntdll!RtlUserThreadStart+0x21

从栈方法 gc_thread_function() 来看,这是一个专有的 GC 线程,熟悉 server GC 的朋友应该知道,用户线程分配 引发GC后,会通过 event 唤醒GC线程,言外之意就是还没有找到这个用户线程触发的导火索,要想找到答案有很多方法,查看当前的 GCSettings 观察 GC 触发的诱因及代数,截图如下:

 

 是一个诱导式FullGC,言外之意就是有代码会调用 GC.Collect() ,接下来我们用 ~*e !clrstack 导出所有的线程栈,观察 GC.Collect() 字样

0:117> !clrstack 
OS Thread Id: 0x170c (117)
        Child SP               IP Call Site
0000007419f1d580 00007ffc69e25ac4 [InlinedCallFrame: 0000007419f1d580] System.GC._Collect(Int32, Int32)
0000007419f1d580 00007ffbfba0fbf2 [InlinedCallFrame: 0000007419f1d580] System.GC._Collect(Int32, Int32)
0000007419f1d550 00007ffbfba0fbf2 Spire.Pdf.PdfDocument.Dispose()
...
0000007419f1e2f0 00007ffc504b1092 System.Web.Mvc.MvcHandler.EndProcessRequest(System.IAsyncResult)

从代码看居然是一个商业组件 Spire.Pdf 在 Dispose 时手工释放触发的,一般这么做的目的是想通过此方法间接释放非托管资源。

其实一个 FullGC 不代表什么,既然线程池堆积了很多任务,除了受到一些诸如 GC 的外因影响,内因肯定是最主要的,既然都是 http 请求,可以用 !whttp 观察各自的 HttpContext。

0:117> !whttp
HttpContext Thread Time Out Running Status Verb Url 0000017b406b6f80 102 00:05:00 00:08:56 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017b46797110 107 00:05:00 00:07:35 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017b814572f8 97 00:05:00 00:08:49 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017b84634490 104 00:05:00 00:07:46 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017bc04767b0 90 00:05:00 00:08:43 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017e3e79cbb8 96 00:05:00 00:09:45 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017e7ee10b80 88 00:05:00 00:09:40 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017e89b2cfb0 109 00:05:00 00:04:37 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017e8adb6b80 106 00:05:00 00:02:53 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017d41e90f28 103 00:05:00 00:08:04 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017d4385d528 101 00:05:00 00:07:39 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017d471b7d58 98 00:05:00 00:06:50 200 GET /xxxx/xxx/xxxLogOutputExcel 0000017bc8283c48 117 00:05:00 00:00:32 200 GET /xxx/xxx/xxxMedTags
...

从卦中看,有两点信息:

  1. 高达 17 个 Excel 导出请求,一般来说导出操作都是 CPU 密集型的, 17 个请求可能刚好把 CPU 全部打满,可以通过 !cpuid 验证下。
0:117> !cpuid
CP F/M/S Manufacturer MHz 0 6,79,1 <unavailable> 1995 1 6,79,1 <unavailable> 1995 2 6,79,1 <unavailable> 1995 3 6,79,1 <unavailable> 1995 4 6,79,1 <unavailable> 1995 5 6,79,1 <unavailable> 1995 6 6,79,1 <unavailable> 1995 7 6,79,1 <unavailable> 1995 8 6,79,1 <unavailable> 1995 9 6,79,1 <unavailable> 1995 10 6,79,1 <unavailable> 1995 11 6,79,1 <unavailable> 1995 12 6,79,1 <unavailable> 1995 13 6,79,1 <unavailable> 1995 14 6,79,1 <unavailable> 1995 15 6,79,1 <unavailable> 1995

!cpuid扩展命令显示有关系统上处理器的信息。

CP列给出处理器编号。(这些数字总是连续的,从零开始)。制造商列指定处理器制造商。MHz列指定处理器速度(如果可用)。对于基于x86或基于x64的处理器,F列显示处理器系列号,M列显示处理器型号,S列显示步进大小。对于基于安腾的处理器,M列显示处理器型号,R列显示处理器修订号,F列显示处理器系列号,A列显示体系结构修订号。

总体来说这次生产事故诱发的因素有两个:

  • 主因是客户高频次的点击 Excel 导出,越着急越点,越点越着急,导致系统的雪崩。

  • 高频的Excel点击操作,间接导致 Spire.Pdf 在某一时段为了释放非托管资源频发的诱导 GC.Collect,进而雪上加霜。

 

标签:00,1995,05,爆高,xxx,GC,CPU,79
From: https://www.cnblogs.com/wwkk/p/16820195.html

相关文章

  • cpu和cache关于内存换入换出
    ##一、内存换入####1.引出换入从前面我们知道,在内存中段页同时存在但是实际情况是虚拟内存的大小一般大于物理内存,我们又不得不实现虚拟内存,所以,用换入换出实现这一差别(......
  • 10、CPU 如何选择线程
    在Linux内核中,进程和线程都是用 ​​task_struct​​ 结构体表示的,区别在于线程的task_struct结构体里部分资源是共享了进程已创建的资源,比如内存地址空间、代码段、......
  • 10、CPU 如何读写数据的?
    先来认识CPU的架构,只有理解了CPU的架构,才能更好地理解CPU是如何读写数据的,对于现代CPU的架构图如下:可以看到,一个CPU里通常会有多个CPU核心,比如上图中的1号和......
  • 8、CPU cache缓存一致性问题
    前面提到过现在CPU都是多核的,由于L1/L2Cache是多个核心各自独有的,L3Cache是多核共用的,那么会带来多核心的缓存一致性(CacheCoherence) 的问题,如果不能保证缓存一致性的......
  • 比较CPU和GPU中的矩阵计算
    GPU计算与CPU相比能够快多少?在本文中,我将使用Python和PyTorch线性变换函数对其进行测试。以下是测试机配置:CPU:英特尔i76700k(4c/8t)GPU:RTX3070TI(6,144个......
  • ZABBIX监控操作系统top10(CPU)
    脚本如下:#!/bin/sh####################################################usedtoCollectionCPUTop10Informatiom#scriptbyshell#writedbyDeliver#huchangxi......
  • 存储器与CPU的连接
    存储器与CPU连接分主要看前五步1.首先根据给出的地址范围写出二进制码2.确定芯片的类型和数量3.确定地址线4.确定片选信号要注意MREQ是低电平有效,要连到138译码器......
  • gpu/cpu类型deployment清单整理脚本
    #!/bin/bashkubectlgetdeploy-nhost|grep-v'0'|awk'{print$1}'>deploy.txtfordeployin`catdeploy.txt`docheck_gpu=`kubectldescribedepl......
  • CPU密集型和IO密集型(判断最大核心线程的最大线程数)
    CPU密集型和IO密集型(判断最大核心线程的最大线程数)CPU密集型1.CPU密集型获取电脑CPU的最大核数,几核,最大线程数就是几Runtime.getRuntime().availableProcessors()--->......
  • linux 监控网络IO、磁盘、CPU、内存
    linux监控网络IO、磁盘、CPU、内存CPU:vmstat,sar–u,top磁盘IO:iostat–xd,sar–d,top网络IO:iftop-n,ifstat,dstat–nt,sar-nDEV23磁盘容量:df–h内存使用:free–m,top......