linux cpu占用率如何看
318
2022-08-22
PerfView专题 (第一篇): 如何寻找热点函数
一:背景
准备开个系列来聊一下 PerfView 这款工具,熟悉我的朋友都知道我喜欢用 WinDbg,这东西虽然很牛,但也不是万能的,也有一些场景他解决不了或者很难解决,这时候借助一些其他的工具来辅助,是一个很不错的主意。
很多朋友喜欢在项目中以记录日志的方式来监控项目的流转情况,其实 CoreCLR 也是这样的,参考如下代码:
void gc_heap::fix_allocation_context (alloc_context* acontext, BOOL for_gc_p, BOOL record_ac_p){ dprintf (3, ("Fixing allocation context %Ix: ptr: %Ix, limit: %Ix", (size_t)acontext, (size_t)acontext->alloc_ptr, (size_t)acontext->alloc_limit));}void gc_heap::background_sweep(){ //concurrent_print_time_delta ("finished with mark and start with sweep"); concurrent_print_time_delta ("Sw"); dprintf (2, ("---- (GC%d)Background Sweep Phase ----", VolatileLoad(&settings.gc_index))); //block concurrent allocation for large objects dprintf (3, ("lh state: planning"));}void gc_heap::background_ephemeral_sweep(){ dprintf (3, ("bgc ephemeral sweep"));}
那这些日志会送到哪里去呢,当然是 Windows 的 ETW 了,那有什么工具可以方便提取呢?PerfView 就是这么其中一款。
这一篇我们做一个 CPU 爆高的场景下如何寻找 热点函数 的例子,看看如何用 PerfView 去挖。
二:PerfView 寻找热点函数
很多场景下的 CPU 高,是因为某个或者某几个线程在高频的执行某个方法,有可能是死循环,有可能是陷入了CPU密集型方法内,解决这个问题一个好的思路就是对 CPU 进行采样,比如我的 12 核电脑。
0:000> !cpuidCP F/M/S Manufacturer MHz 0 6,5,2 2592 1 6,5,2 2592 2 6,5,2 2592 3 6,5,2 2592 4 6,5,2 2592 5 6,5,2 2592 6 6,5,2 2592 7 6,5,2 2592 8 6,5,2 2592 9 6,5,2 259210 6,5,2 259211 6,5,2 2592
1. 如何采样
采样的原理就是周期性的去看下当前的 CPU 核中运行的几个线程正在执行什么方法, 当采样到了几万个或者几十万个样本之后,就可以对这些采集到的方法进行分组排序来找到 topN,那些 TopN 的方法自然就是导致 CPU 爆高可能的诱因。
windbg 有一个 !running 命令可以用来显示当前处理器中正在运行的线程。
lkd> !runningSystem Processors: (0000000000000fff) Idle Processors: (000000000000065e) Prcbs Current (pri) Next (pri) Idle 0 fffff80268a33180 ffffaf8ec9bd8080 (15) fffff8026b526600 ................ 5 ffffd900e1700180 ffffaf8eca36b080 ( 8) ffffd900e170b340 ................ 7 ffffd900e1900180 ffffaf8ec2f18080 ( 8) ffffd900e190b340 ................ 8 ffffd900e1a00180 ffffd900e1a0b340 ( 0) ffffd900e1a0b340 ................ 11 ffffd900e1d00180 ffffaf8eb6bee080 ( 8) ffffd900e1d0b340 ................
接下来写一个程序,让其中一个线程无限循环,然后通过 PerfView 去找这个热点。
internal class Program { static void Main(string[] args) { Task.Run(() => Test1()); //Test1 故意死循环 Task.Run(() => Test2()); //Test2 是一个正常函数 Console.WriteLine("我是主线程!"); Console.ReadLine(); } static void Test1() { var i = 10; var b = true; while (i > 0) { b = !b; } } static void Test2() { for (int i = 0; i < 10000; i++) { var j = string.Join(",", Enumerable.Range(0, 100)); } Console.WriteLine("Test执行结束"); } }
2. 使用 PerfView 采样
在这个面板中,选中如下几项。
1)CPU Samples:
设置对 CPU 进行采样。
2)CPU Sample Interval Msec
设置采样的频次是 1ms/次。
3)Max Collect Sec
设置总共采样多少秒,这里设置为 15 秒。
4).NET Symbol Collection
用来从微软符号服务器上拉取符号,和采样无关哈。
从图中可以看到,当前采样了 15622 个样本,符合 15 * 1000 ,接下来把上面的 GroupPats 默认分组给清掉,截图如下:
从图中可以看到当前 Test1() 方法在 15622 个样本中占比 97.9%,命中次数高达 15290 次,很明显这是一个绝对的 热点函数,接下来就是翻源码为什么 Test1 这么高频?
好了,本篇就先聊这么多吧。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~