高 CPU 使用率 perf .net 应用程序

Posted

技术标签:

【中文标题】高 CPU 使用率 perf .net 应用程序【英文标题】:Hight CPU usage perf .net application 【发布时间】:2017-05-01 11:02:14 【问题描述】:

我正在尝试分析我用C# 编写的.net 应用程序,它使用了100% 的cpu。应用程序很大,包含大量代码,因此无法提供整个项目代码。我试图为使用 25% CPU(1 个核心)的应用程序线程获取线程堆栈,但我经常得到这个:

ntoskrnl.exe!KeSynchronizeExecution+0x2246
ntoskrnl.exe!KeWaitForMultipleObjects+0x135e
ntoskrnl.exe!KeWaitForMultipleObjects+0xdd9
ntoskrnl.exe!KeWaitForMutexObject+0x373
ntoskrnl.exe!KeStallWhileFrozen+0x1977
ntoskrnl.exe!_misaligned_access+0x13f9
ntoskrnl.exe!KeWaitForMultipleObjects+0x152f
ntoskrnl.exe!KeWaitForMultipleObjects+0xdd9
ntoskrnl.exe!KeWaitForMutexObject+0x373
ntoskrnl.exe!NtWaitForSingleObject+0xb2
ntoskrnl.exe!setjmpex+0x34a3
ntdll.dll!ZwWaitForSingleObject+0xa
KERNELBASE.dll!WaitForSingleObjectEx+0x98
clr.dll!GetMetaDataInternalInterface+0x25b1f
clr.dll!GetMetaDataInternalInterface+0x25ad3
clr.dll!GetMetaDataInternalInterface+0x25a92
clr.dll!GetMetaDataInternalInterface+0x39106
clr.dll!GetMetaDataInternalInterface+0x39a81
clr.dll!GetMetaDataInternalInterface+0x394ad
clr.dll!GetMetaDataInternalInterface+0x39979
clr.dll!GetMetaDataInternalInterface+0x398c1
clr.dll!GetMetaDataInternalInterface+0x3539a
clr.dll!ClrCreateManagedInstance+0x2747
KERNEL32.dll!BaseThreadInitThunk+0x22
ntdll.dll!RtlUserThreadStart+0x34
谁能向我解释为什么带有这个调用堆栈的线程会消耗 1 个核心 我的CPU? “KeSynchronizeExecution”是什么意思? 在这种情况下如何避免 CPU 使用率过高?

【问题讨论】:

这个堆栈跟踪的质量很差,当你想看到机器的灵魂时,获取操作系统的PDB是非常重要的。工具 > 选项 > 调试 > 符号 > 勾选“Microsoft 符号服务器”并选择符号缓存目录。 Fwiw,此跟踪没有显示任何关于性能问题的体面提示,WaitForSingleObjectEx() 是一个阻塞线程的同步函数。到目前为止,最好的办法是使用分析器,这样您就可以看到昂贵的代码。 【参考方案1】:

只是想在这里帮助你,我不是专家。

ntoskrnl.exe!KeSynchronizeExecution 例程将指定例程的执行与分配给一组一个或多个中断对象的中断服务例程 (ISR) 同步。

ntoskrnl.exe!KeWaitForMultipleObjects 例程将当前线程置于可警告或不可警告等待状态,直到任何或所有调度程序对象设置为信号状态或(可选)直到等待超时。

ntoskrnl.exe!KeWaitForMutexObject 例程将当前线程置于可警报或不可警报等待状态,直到给定的互斥对象设置为信号状态或(可选)直到等待超时。

我认为 ntoskrnl.exe!KEStallWhileFrozen 例程在等待多个对象例程未解决时被调用。

ntoskrnl.exe!_misaligned_access 例程在 cpu 无法读取未对齐数据时发出警报。似乎未对齐的内存访问会在硬件中不支持它们的目标上导致巨大的性能损失。参考:https://msdn.microsoft.com/en-us/library/ms253949(v=vs.80).aspx。还要检查避免对齐错误部分。

ntoskrnl.exe!NtWaitForSingleObject 等到指定对象达到信号状态。

调用 setjmp 函数可以保存当前指令地址以及其他 CPU 寄存器。对 longjmp 函数的后续调用将恢复指令指针和寄存器,并在 setjmp 调用之后的点继续执行。

ntdll.dll!ZwWaitForSingleObject 例程一直等到指定的对象达到 Signaled 状态。也可以指定一个可选的超时时间。

KERNELBASE.dll!WaitForSingleObjectEx 等到指定对象处于信号状态、I/O 完成例程或异步过程调用 (APC) 排队到线程或超时间隔过去了。

clr.dll!GetMetaDataInternalInterface 获取指向用于在内存中读取和写入元数据的内部接口实例的指针。

【讨论】:

【参考方案2】:

我之前为此使用过 Jetbrains 解决方案。它真的可以很容易地找到优化点。我的建议使用:https://www.jetbrains.com/profiler/ 并找出哪些进程和方法使用率高。你也可以找到内存等。

我知道你可以安装试用。安装试用并解决您的问题。

【讨论】:

以上是关于高 CPU 使用率 perf .net 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

使用 perf 监控每个 CPU 的内存访问

linux 性能优化-- cpu 切换以及cpu过高

Linux中CPU性能分析工具perf简单使用(亲测可用)

Linux 性能优化利用perf和CPU使用率定位异常函数

perf界面乱码

高规格虚机 sys cpu高现场分析工具箱