记一次 .NET某设备监控自动化系统 CPU爆高分析
一:背景
1. 讲故事
先说一下题外话,一个监控别人系统运行状态的程序,结果自己出问题了,有时候想一想还是挺讽刺的,哈哈,开个玩笑,我们回到正题,前些天有位朋友找到我,说他们的系统会偶发性CPU爆高,CPU上去了就下不来了,让我帮忙看一下怎么回事,而且自己也分析过了,没找到哪里有问题,写监控的都是高手,给我的第一感觉就是这个dump可能解决起来不容易,不管怎么说,有了dump就开干吧!
二:WinDbg 分析
1. CPU真的爆高吗
作为调试人,第一准则就是不要轻信任何人透露给你的信息,因为人家在这块是一个小白,往往他的信息会把你带偏,我们只相信数据即可,切记!!! 所以我们先用 !tp 观察下CPU使用率。
0:198> !tp
CPU utilization: 100%
Worker Thread: Total: 197 Running: 42 Idle: 154 MaxLimit: 32767 MinLimit: 8
Work Request in Queue: 0
--------------------------------------
Number of Timers: 0
--------------------------------------
Completion Port Thread:Total: 10 Free: 5 MaxFree: 16 CurrentLimit: 10 MaxLimit: 1000 MinLimit: 8
从卦中信息看当前 CPU=100%,还是蛮惨的,那到底谁在吃CPU资源呢?根据经验先查一下是不是触发了2代GC,接下来用 !t 观察下是否有GC标记。
0:198> !t
ThreadCount: 214
UnstartedThread: 0
BackgroundThread: 211
PendingThread: 0
DeadThread: 1
Hosted Runtime: noLock ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception0 1 276f0 000002789526b5f0 2a020 Preemptive 0000000000000000:0000000000000000 000002789525e840 0 MTA 2 2 25e5c 0000027895296d00 2b220 Preemptive 0000000000000000:0000000000000000 000002789525e840 0 MTA (Finalizer) 3 3 260e8 00000278ae35f0c0 202b020 Preemptive 0000000000000000:0000000000000000 000002789525e840 0 MTA ...169 2113 10c20 00000278c26766c0 1029220 Preemptive 00000278B5D7D188:00000278B5D7D188 000002789525e840 1 MTA (GC) (Threadpool Worker) xxxException 00000278b5d46ce0...
尼玛从卦中的 (GC) 来看,还真的触发了GC,接下来的研究方向就是洞察下是不是CPU爆高的祸首。
2. GC触发导致的吗
要寻找这个问题的答案,首先就是看下这次GC是不是 FullGC 即可,可以切到 169 号线程,观察下线程栈。
0:169> k 10# Child-SP RetAddr Call Site
00 000000c4`36ffb798 00007ffc`d5f14313 ntdll!NtWaitForSingleObject+0x14
01 000000c4`36ffb7a0 00007ffc`c927cb27 KERNELBASE!WaitForSingleObjectEx+0x93
02 000000c4`36ffb840 00007ffc`c927cadf clr!CLREventWaitHelper2+0x3c
03 000000c4`36ffb880 00007ffc`c927ca5c clr!CLREventWaitHelper+0x1f
04 000000c4`36ffb8e0 00007ffc`c926bd32 clr!CLREventBase::WaitEx+0x7c
05 000000c4`36ffb970 00007ffc`c9269bc4 clr!ThreadSuspend::SuspendRuntime+0x32c
06 000000c4`36ffba60 00007ffc`c91814e3 clr!ThreadSuspend::SuspendEE+0x128
07 000000c4`36ffbb60 00007ffc`c9185f51 clr!WKS::GCHeap::GarbageCollectGeneration+0xb7
08 000000c4`36ffbbc0 00007ffc`c9260f56 clr!WKS::gc_heap::trigger_gc_for_alloc+0x2d
09 000000c4`36ffbc00 00007ffc`c6b0f7e7 clr!JIT_NewArr1+0xa97
0a 000000c4`36ffc030 00007ffc`6a388270 mscorlib_ni!System.String.ToCharArray+0x27 [f:\dd\ndp\clr\src\BCL\system\string.cs @ 758]
0b 000000c4`36ffc080 00007ffc`6a3880ed 0x00007ffc`6a388270
0c 000000c4`36ffc100 00007ffc`6a56056d 0x00007ffc`6a3880ed
0d 000000c4`36ffc150 00007ffc`6a3cd749 0x00007ffc`6a56056d
0e 000000c4`36ffc1b0 00007ffc`c911989d 0x00007ffc`6a3cd749
0f 000000c4`36ffc220 00007ffc`c9119764 clr!ExceptionTracker::CallHandler+0xfd
从卦中看此时的GC还处于早期的 SuspendEE 阶段,无法获取内部的 settings 结构,这就比较麻烦了,那怎么办呢?只能看看 GarbageCollectGeneration 的第一个参数有没有保存在栈中,要是没有就惨了。。。方法签名如下:
size_t
GCHeap::GarbageCollectGeneration (unsigned int gen, gc_reason reason)
{}
根据 x64调用协定,gen是保存在 rdx 寄存器里,接下来观察汇编代码。
0:000> uf 00007ffc`c91814e3
clr!WKS::GCHeap::GarbageCollectGeneration:
00007ffc`c918142c 48895c2418 mov qword ptr [rsp+18h],rbx
00007ffc`c9181431 89542410 mov dword ptr [rsp+10h],edx
00007ffc`c9181435 48894c2408 mov qword ptr [rsp+8],rcx
00007ffc`c918143a 55 push rbp
00007ffc`c918143b 56 push rsi
00007ffc`c918143c 57 push rdi
00007ffc`c918143d 4154 push r12
00007ffc`c918143f 4155 push r13
00007ffc`c9181441 4156 push r14
00007ffc`c9181443 4157 push r15
...0:169> dd 000000c4`36ffbbc0-0x8+0x10 L1
000000c4`36ffbbc8 00000000
从卦中看,谢天谢地,edx保存在 rsp+10h 的位置,通过dp观察内存地址的值发现是0,也就表示当前是 0 代GC,这种smallgc 经常触发是很正常的,并不是我们CPU爆高的诱因,接下来就陷入迷茫了。。。
3. 路在何方
撞了南墙之后得要看看其他路子,其实刚才用 !t 观察线程列表的时候我就注意到一个特征,那就是很多线程上挂了异常,截图如下:

从卦中看此时有19个线程在抛 xxxResultException 异常,做过开发的朋友都知道,如果频繁的抛异常是很耗CPU资源的,因为它要设计到用户态到内核态的切换,如果有 19 个线程一起抛异常,那绝对是一个灾难。。。
有些朋友说我cpu猛一点是不是就可以了,哈哈,理论上是可以的,可以用 !cpuid 观察下这台机器的cpu核心数。
0:169> !cpuid
CP F/M/S Manufacturer MHz0 6,167,1 <unavailable> 34081 6,167,1 <unavailable> 34082 6,167,1 <unavailable> 34083 6,167,1 <unavailable> 34084 6,167,1 <unavailable> 34085 6,167,1 <unavailable> 34086 6,167,1 <unavailable> 34087 6,167,1 <unavailable> 3408
从证据链的完整性上来说,其实这里还需要再做一个验证,就是19个线程抛异常不代表他们的并发性,言外之意就是能不能再找一些其他证据,怎么找其他证据呢?
做C#开发的朋友应该知道,Exception 属于引用类型,如果密集抛了很多异常,那托管堆上自然就有很多,直到GC回收,所以我们观察下这个时间差即可,使用 !wdae 命令,这里为了隐私性我就模糊了哈。
0:169> !wdae384 of Type: xxxResultException 000002789fdb6478 000002789fdb69b0 000002789fdb9848
Message: xxxFailed
Inner Exception: (none)
Stack:
IP Function
00007ffc6a269861 xxx.ChannelAsyncOperation`1[[System.Int32, mscorlib]].End(Int32, Boolean)
...411 of Type: xxxResultException 000002789fdb6e90 000002789fdb7090 000002789fdb72a8
Message: xxxClosed
Inner Exception: (none)
Stack:
IP Function
00007ffc6a269861 xxx.ChannelAsyncOperation`1[[System.Int32, mscorlib]].End(Int32, Boolean)
...
808 Exceptions in 12 unique type/stack combinations (duplicate types in similar stacks may be rethrows)
从卦中看当前抛了808个异常,大多是和channel通信有关,结合16个线程并发抛,这就稳了,看样子cpu爆高期间就是由于高频的抛异常所致,分析出这些信息之后,就是告诉朋友把这些异常给解决掉即可。
三:总结
CPU爆高的诱因非常多,高频的抛异常就属于其中一例,其实这种通信时发生了突发异常正是 Polly 这种 弹性和瞬态故障处理库 大显身手的地方。
相关文章:
记一次 .NET某设备监控自动化系统 CPU爆高分析
一:背景 1. 讲故事 先说一下题外话,一个监控别人系统运行状态的程序,结果自己出问题了,有时候想一想还是挺讽刺的,哈哈,开个玩笑,我们回到正题,前些天有位朋友找到我,说…...
大数据与云计算
目录 一、大数据时代二、云计算——大数据的计算三、云计算发展现状四、云计算实现机制五、云计算压倒性的成本优势 一、大数据时代 我们先来看看百度关于 “大数据”(Big Data)的搜索指数。 可以看出,“大数据” 这个词是从2012年才引起关注…...
一. 并行处理与GPU体系架构-并行处理简介
目录 前言0. 简述1. 串行处理与并行处理的区别2. 并行执行3. 容易混淆的几个概念4. 常见的并行处理总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习下课程第一章——并行处…...
vb机试考试成绩分析与统计,设计与实现(高数概率统计)-141-(代码+程序说明)
转载地址http://www.3q2008.com/soft/search.asp?keyword141 前言: 为何口出狂言,作任何VB和ASP的系统, 这个就是很好的一个证明 :) 又有些狂了... 数据库操作谁都会,接触的多了也没什么难的,VB编程难在哪?算法上,这个是一个算法题的毕业设计,里面涉及到对试卷的 平均分,最…...
Arm MMU深度解读
文章目录 一、MMU概念介绍二、虚拟地址空间和物理地址空间2.1、(虚拟/物理)地址空间的范围2.2、物理地址空间有效位(范围) 三、Translation regimes四、地址翻译/几级页表?4.1、思考:页表到底有几级?4.2、以4KB granule为例,页表的…...
2024 年 AI 辅助研发趋势
在2024年,AI辅助研发的应用趋势将非常广泛。举个例子,比如在医疗健康领域,AI将深度参与新药研发、早期癌症研究以及辅助诊断等,助力医疗技术的突破。同时,在农业领域,AI也将通过无人机、智能装备等方式&…...
聊聊pytho中的函数
Python中的函数 一、Python中函数的作用与使用步骤 1、为什么需要函数 在Python实际开发中,我们使用函数的目的只有一个“让我们的代码可以被重复使用” 函数的作用有两个: ① 代码重用(代码重复使用) ② 模块化编程&#x…...
Python中starmap有什么用的?
目录 前言 starmap函数的作用 starmap函数的用法 starmap函数的示例 1. 对每个元组元素进行求和 2. 对每个元组元素进行乘积 实际应用场景 1. 批量处理函数参数 2. 并行处理任务 3. 批量更新数据库 总结 前言 在Python中, starmap 是一个非常有用的函数&…...
面向切面编程 AOP
提示:主要内容参考动力节点老杜的Spring6讲义。 面向切面编程 AOP 一、AOP介绍二、AOP的七大术语三、切点表达式 IoC使软件组件松耦合。AOP让你能够捕捉系统中经常使用的功能,把它转化成组件。AOP(Aspect Oriented Programming)&a…...
POS 之 奖励机制
为什么需要有奖惩机制 如果没有奖励,就不会有节点参与POS,运营节点有成本,而奖励正是让运营者获利的方式 如果没有惩罚,网络上会充斥着很多无效节点,会扰乱甚至破坏网络 所有奖励和惩罚在每个 Epoch 实施一次 奖励 什…...
Unity类银河恶魔城学习记录9-7 p88 Crystal instead of Clone源代码
Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Blackhole_Skill_Controller.cs using System.Collections; using System…...
导出RWKV模型为onnx
测试模型: https://huggingface.co/RWKV/rwkv-5-world-3b 导出前对modeling_rwkv5.py进行一个修改: # out out.reshape(B * T, H * S) out out.reshape(B * T, H * S, 1) # <<--- modified out F.group_norm(out, nu…...
【LeetCode】整数转罗马数字 C语言 | 此刻,已成艺术(bushi)
Problem: 12. 整数转罗马数字 文章目录 思路解题方法复杂度Code 思路 暴力破解 转换 解题方法 由思路可知 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( 1 ) O(1) O(1) Code char* intToRoman(int num) {char *s (char*)malloc(sizeof(char)*4000), *p s;while(…...
移动App开发常见的三种模式:原生应用、H5移动应用、混合模式应用
引言 在移动应用市场的迅猛发展中,移动App开发正日益成为技术创新和用户体验提升的焦点。对于开发者而言,选择适合自己项目的开发模式成为至关重要的决策。本文将探究移动App开发的三种常见模式:原生应用、H5移动应用和混合模式应用。这三种…...
k8s Secret配置资源,ConfigMap 存储配置信资源管理详解
目录 一、Secret 概念 三种Secret类型 pod三种使用secret的方式 应用场景:凭据: 二、 示例 2.1、用kubectl create secret命令创建 Secret 创建Secret: 查看Secret列表: 描述Secret: 2.2、用 base64 编码&…...
POS 之 最终确定性
Gasper Casper 是一种能将特定区块更新为 最终确定 状态的机制,使网络的新加入者确信他们正在同步规范链。当区块链出现多个分叉时,分叉选择算法使用累计投票来确保节点可以轻松选择正确的分叉。 最终确定性 最终确定性是某些区块的属性,意味…...
Vue快速开发一个主页
前言 这里讲述我们如何快速利用Vue脚手架快速搭建一个主页。 页面布局 el-container / el-header / el-aside / el-main:https://element.eleme.cn/#/zh-CN/component/container <el-container><el-header style"background-color: #4c535a"…...
Java SE入门及基础(33)
final 修饰符 1. 应用范围 final 修饰符应该使用在类、变量以及方法上 2. final 修饰类 Note that you can also declare an entire class final. A class that is declared final cannot be subclassed. This is particularly useful, for example, when creating an imm…...
ChatGPT逐步进入留学圈但并不能解决留学规划的问题
2022 年底,一个能像人类一样对话的AI软件ChatGPT,在5天内突破一百万用户,风靡全球,如今用户已达1.8亿。 四个月后,ChatGPT进化为GPT4版本。该版本逻辑、数学推理能力卓越。拿留美标准化考试举例,GPT4能够在…...
WebGL之灯光使用解析
在使用灯光之前,首先我们需要了解,与定义更广泛的 OpenGL 不同,WebGL 并没有继承 OpenGL 中灯光的支持。所以你只能由自己完全得控制灯光。幸运得是,这也并不是很难,本文接下来就会介绍完成灯光的基础。 在 3D 空间中…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
