- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
前些天训练营里的一位学员找到我,说他们的差旅后台系统出现了CPU爆高的情况,爆高之后就下不去了,自己分析了下也没找到原因,事情比较紧急,让我帮忙看下是什么回事,手里也有dump,丢过我之后我们上 windbg 分析吧.
看过这个系列的朋友都知道CPU是否爆高,可以用 !tp 命令来验证,参考输出如下:
0:000> !tp
CPU utilization: 100%
Worker Thread: Total: 66 Running: 66 Idle: 0 MaxLimit: 32767 MinLimit: 4
Work Request in Queue: 93
Unknown Function: 00007ffc744f1750 Context: 000002c3acdad7d8
AsyncTimerCallbackCompletion TimerInfo@000002bf57193d20
Unknown Function: 00007ffc744f1750 Context: 000002c3acb2aef0
...
Unknown Function: 00007ffc744f1750 Context: 000002c3ad336718
--------------------------------------
Number of Timers: 0
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 8 CurrentLimit: 1 MaxLimit: 1000 MinLimit: 4
从卦中的 CPU utilization: 100% 可以确认此时CPU被打满了,同时也有一个现象就是这个线程池队列有堆积的情况,一般来说堆积就表示下游处理不力,常常表现为程序卡死,Http超时,和 CPU爆高问题 没有直接关系,这是一个经验问题,大家一定要甄别,以免陷入误区.
接下来我们看下这台机器的CPU能力如何,能力越弱越容易被打爆,可以用 !cpuid 观察.
0:000> !cpuid
CP F/M/S Manufacturer MHz
0 6,85,7 <unavailable> 2095
1 6,85,7 <unavailable> 2095
2 6,85,7 <unavailable> 2095
3 6,85,7 <unavailable> 2095
从卦中可以看到当前的 CPU=4core,只要4个满负荷的Thread就可以轻松打爆,接下来我们的研究方向在哪里呢?对,就是从 Thread 入手.
要想看线程都在干什么?可以使用 ~*e !clrstack 观察即可,参考输出如下:
OS Thread Id: 0x968 (87)
Child SP IP Call Site
000000e63babb9a8 00007ffc879a6974 [GCFrame: 000000e63babb9a8]
000000e63babba78 00007ffc879a6974 [HelperMethodFrame_1OBJ: 000000e63babba78] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object)
000000e63babbb90 00007ffc5e735bbf System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken) [f:\dd\ndp\clr\src\BCL\system\threading\ManualResetEventSlim.cs @ 669]
000000e63babbc20 00007ffc5e72e9c5 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Task.cs @ 3320]
000000e63babbc90 00007ffc5f0cc188 System.Threading.Tasks.Task.InternalWait(Int32, System.Threading.CancellationToken) [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Task.cs @ 3259]
000000e63babbd60 00007ffc5f0c9176 System.Threading.Tasks.Task`1[[System.__Canon, mscorlib]].GetResultCore(Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Future.cs @ 559]
000000e63babbda0 00007ffc1b98f2cf xxxCheckFilterAttribute.GetRequestParameter(System.Web.Http.Controllers.HttpActionContext)
...
从卦中可以看到大量的 Wait 等待,其实就是代码中调用 Task.Result 所致,即异步中混合同步,虽然这是一个可能导致线程饥饿的问题,但和我们的目标:CPU爆高无关,所以我们需要在茫茫调用栈中寻找其他可能导致的 CPU 爆高线程,经过仔细而耐心的查找,终于找到了疑似调用栈,刚好有5个都停留在这个位置。参考如下:
OS Thread Id: 0x26a8 (35)
Child SP IP Call Site
000000e62537b048 00007ffc879a64a4 [HelperMethodFrame: 000000e62537b048]
000000e62537b190 00007ffc5e68e04a System.String.Concat(System.String, System.String) [f:\dd\ndp\clr\src\BCL\system\string.cs @ 3207]
000000e62537b1e0 00007ffc1dbe85eb xxx.GetParentDeptName_All(System.Collections.Generic.List`1<xxx.xxxDepts>, Int64)
...
000000e62537c870 00007ffc1e0af75b DynamicClass.lambda_method(System.Runtime.CompilerServices.Closure, System.Object, System.Object[])
000000e62537c8b0 00007ffc1b29b3b8 System.Web.Http.Controllers.ReflectedHttpActionDescriptor+ActionExecutor+c__DisplayClass10.b__9(System.Object, System.Object[])
000000e62537c8f0 00007ffc1b29a768 System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(System.Web.Http.Controllers.HttpControllerContext, System.Collections.Generic.IDictionary`2<System.String,System.Object>, System.Threading.CancellationToken)
000000e62537c950 00007ffc1b29a18e System.Web.Http.Controllers.ApiControllerActionInvoker+d__0.MoveNext()
000000e62537c9c0 00007ffc1b2996ca System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.__Canon, mscorlib]].Start[[System.Web.Http.Controllers.ApiControllerActionInvoker+d__0, System.Web.Http]](d__0 ByRef)
000000e62537ca70 00007ffc1b299611 System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsyncCore(System.Web.Http.Controllers.HttpActionContext, System.Threading.CancellationToken)
000000e62537cb30 00007ffc1b299535 System.Web.Http.Controllers.ApiControllerActionInvoker.InvokeActionAsync(System.Web.Http.Controllers.HttpActionContext, System.Threading.CancellationToken)
000000e62537cb60 00007ffc1b299504 System.Web.Http.Controllers.ActionFilterResult.b__0(ActionInvoker)
000000e62537cb90 00007ffc1b2994a9 System.Web.Http.Controllers.ActionFilterResult+c__DisplayClass10`1[[System.Web.Http.Controllers.ActionFilterResult+ActionInvoker, System.Web.Http]].b__f()
000000e62537cbe0 00007ffc1b2622f9 System.Web.Http.Filters.ActionFilterAttribute+d__5.MoveNext()
000000e62537cc40 00007ffc1b261cfa System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.__Canon, mscorlib]].Start[[System.Web.Http.Filters.ActionFilterAttribute+d__5, System.Web.Http]](d__5 ByRef)
000000e62537ccf0 00007ffc1b261bf4 System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(System.Web.Http.Controllers.HttpActionContext, System.Threading.CancellationToken, System.Func`1<System.Threading.Tasks.Task`1<System.Net.Http.HttpResponseMessage>>)
000000e62537cdd0 00007ffc1b2584d4 System.Web.Http.Filters.ActionFilterAttribute+d__0.MoveNext()
到了这里之后,甭管有没有问题,反正嫌疑很大,接下来就得研究 GetParentDeptName_All 方法.
要想知道有没有问题,我们用 ILSpy观察其源码,由于客户隐私的问题,这里就稍微模糊一下,截图如下:
从卦中看,尼玛,还真有一个 while 逻辑,一下子就提起了我的兴趣,看样子八九不离十,接下来到线程栈上 GetParentDeptName_All 方法的 listDept 和 deptId 参数给挖出来,我们从35号线程入手,使用 !clrstack -a 参数观察输出结果.
0:035> !clrstack -a
OS Thread Id: 0x26a8 (35)
Child SP IP Call Site
000000e62537b048 00007ffc879a64a4 [HelperMethodFrame: 000000e62537b048]
000000e62537b190 00007ffc5e68e04a System.String.Concat(System.String, System.String) [f:\dd\ndp\clr\src\BCL\system\string.cs @ 3207]
PARAMETERS:
str0 (<CLR reg>) = 0x000002c05816f360
str1 (<CLR reg>) = 0x000002c3e21eaf88
LOCALS:
<no data>
<no data>
000000e62537b1e0 00007ffc1dbe85eb xxx.GetParentDeptName_All(System.Collections.Generic.List`1<xxxDepts>, Int64)
PARAMETERS:
this (0x000000e62537b2c0) = 0x000002c059898590
listDept (0x000000e62537b2c8) = 0x000002c159803390
deptId (0x000000e62537b2d0) = 0x00000000000324fb
拿到了 listDept 的地址之后,用 .logopen 把 !mdt -e:2 000002c159803390 的输出结果全部记录到文本文件,为了保护客户隐私,这里就不截图了,直接上文本.
[20828] 000002c059802b68 (xxxtDepts)
<DeptId>k__BackingField:0x324fb (System.Int32)
<ParentDeptId>k__BackingField:0x31347 (System.Int32)
...
[20643] 000002c0597f0e30 (xxxtDepts)
<DeptId>k__BackingField:0x2f240 (System.Int32)
<ParentDeptId>k__BackingField:0x31347 (System.Int32)
...
[20663] 000002c0597f2d18 (xxxtDepts)
<DeptId>k__BackingField:0x2f254 (System.Int32)
<ParentDeptId>k__BackingField:0x2f240 (System.Int32)
...
从卦中数据看,listDept数组的第 20643 和 20663 项的子节点和父节点是循环的,这自然就导致了死循环,所以这次生产事故本质上是数据导致的,将结果反馈给朋友,也得到了确认.
问题找到了之后,解决办法也比较简单.
校正数据.
可以设置循环上限,如果超过某个阈值,直接抛出异常,这样可以避免出现CPU爆高导致的机器级别故障 。
PS: .net core 版本的 Dictionary 就是这么干的,参考代码如下:
在 .net framework 中就会出现傻乎乎打爆的严重事件.
我的学员没有分析出来,我觉得应该是被 Task.Result 给误导了,真实的dump分析可能会真真假假,假假真真,就像这个社会一样,需要更多的实践历练吧.
最后此篇关于记一次.NET某差旅系统CPU爆高分析的文章就讲到这里了,如果你想了解更多关于记一次.NET某差旅系统CPU爆高分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我刚刚继承了一个旧的 PostgreSQL 安装,需要进行一些诊断以找出该数据库运行缓慢的原因。在 MS SQL 上,您可以使用 Profiler 等工具来查看正在运行的查询,然后查看它们的执行计划。
将目标从Analytics(分析)导入到AdWords中,然后在Analytics(分析)中更改目标条件时,是否可以通过更改将目标“重新导入”到AdWords,还是可以自动选择? 最佳答案 更改目标值
我正在使用google analytics api来获取数据。我正在获取数据,但我想验证两个参数,它们在特定日期范围内始终为0。我正在获取['ga:transactions']和['ga:goalCo
我使用Google API从Google Analytics(分析)获取数据,但指标与Google Analytics(分析)的网络界面不同。 即:我在2015年3月1日获得数据-它返回综合浏览量79
我在我的Web应用程序中使用sammy.js进行剔除。我正在尝试向其中添加Google Analytics(分析)。我很快找到了following plugin来实现页面跟踪。 我按照步骤操作,页面如
当使用 Xcode 分析 (product>analyze) 时,有没有办法忽略给定文件中的任何错误? 例如编译指示之类的? 我们只想忽略第三方代码的任何警告,这样当我们的代码出现问题时,它对我们
目录 EFK 1. 日志系统 2. 部署ElasticSearch 2.1 创建handless服务 2.2 创建s
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
GCC/G++ 是否有可用于输出分析的选项? 能够比较以前的代码与新代码之间的差异(大小、类/结构的大小)将很有用。然后可以将它们与之前的输出进行比较以进行比较,这对于许多目的都是有用的。 如果没有此
我正在浏览 LYAH,并一直在研究处理列表时列表理解与映射/过滤器的使用。我已经分析了以下两个函数,并包含了教授的输出。如果我正确地阅读了教授的内容,我会说 FiltB 的运行速度比 FiltA 慢很
在 MySQL 中可以使用 SET profiling = 1; 设置分析 查询 SHOW PROFILES; 显示每个查询所用的时间。我想知道这个时间是只包括服务器的执行时间还是还包括将结果发送到前
我用 Python 编写了几个用于生成阶乘的模块,我想测试运行时间。我找到了一个分析示例 here我使用该模板来分析我的模块: import profile #fact def main():
前几天读了下mysqld_safe脚本,个人感觉还是收获蛮大的,其中细致的交代了MySQL数据库的启动流程,包括查找MySQL相关目录,解析配置文件以及最后如何调用mysqld程序来启动实例等,有着
上一篇:《人工智能大语言模型起源篇,低秩微调(LoRA)》 (14)Rae 和同事(包括78位合著者!)于2022年发表的《Scaling Language Models: Methods, A
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
1 内网基础 内网/局域网(Local Area Network,LAN),是指在某一区域内有多台计算机互联而成的计算机组,组网范围通常在数千米以内。在局域网中,可以实现文件管理、应用软件共享、打印机
我有四列形式的数据。前三列代表时间,value1,value 2。第四列是二进制,全为 0 或 1。当第四列中对应的二进制值为0时,有没有办法告诉excel删除时间、值1和值2?我知道这在 C++ 或
我正在运行一个进行长时间计算的 Haskell 程序。经过一些分析和跟踪后,我注意到以下内容: $ /usr/bin/time -v ./hl test.hl 9000045000050000 Com
我有一个缓慢的 asp.net 程序正在运行。我想分析生产服务器以查看发生了什么,但我不想显着降低生产服务器的速度。 一般而言,配置生产盒或仅本地开发盒是标准做法吗?另外,您建议使用哪些程序来实现这一
我目前正在尝试分析 Haskell 服务器。服务器永远运行,所以我只想要一个固定时间的分析报告。我尝试只运行该程序 3 分钟,然后礼貌地要求它终止,但不知何故,haskell 分析器不遵守术语信号,并
我是一名优秀的程序员,十分优秀!