赞
踩
本篇是我们系列文章的最后一篇,前面的文章中大多是在 CLR Runtime
以及 OS
层面进行监控来发现各种可疑的程序问题,除了这两个层面,其实我们还可以对 SDK 中一些类进行洞察,比如说:
ArrayPool
Http
Socket
Task
更多资料可以看下:https://docs.microsoft.com/en-us/dotnet/core/diagnostics/well-known-event-providers
接下来就来个简单的抛砖引玉
之所以对 ArrayPool 感兴趣,主要还是因为在分析 Dump 的过程中,遇到过几起 LOH 碎片化问题,比如使用第三方模板生成引擎生成 Html 导致大量临时性 char[]
, byte[]
,终导致 LOH 破败不堪,所以最后给出的建议是使用这种池化的 ArrayPool
,如果可以监控池的租借情况,那是不是挺好的?哈哈,还真有这样的 ETW,截图如下:
为了方便讲解,先上一段简单的测试代码:
- internal class Program
- {
- static void Main(string[] args)
- {
- var shared = ArrayPool<int>.Shared;
-
- var rentedArray = shared.Rent(10);
-
- for (int i = 0; i < 10; i++)
- {
- rentedArray[i] = i + 1;
- }
-
- for (int j = 0; j < 10; j++)
- {
- Console.WriteLine(rentedArray[j]);
- }
-
- shared.Return(rentedArray);
-
- Console.ReadKey();
- }
- }
接下来启动 Perfview,在 Additional Providers 上输入:
*System.Buffers.ArrayPoolEventSource:::@StacksEnabled=true
然后开启 Start Collection
观察 Array 的租借情况,稍等片刻后,在 Event 中搜索 ArrayPool
可以看到相关的 ETW 事件,截图如下:
在 Rent
列的 bufferSize="16"
中可知,当前租借了一个 size=16
的数组。
HasStack="True" ThreadID="15,060" ProcessorNumber="10" bufferId="32,854,180" bufferSize="16" poolId="27,252,167" bucketId="-1"
因为开启了 Stack
功能,可以在 Time MSec
列上右键选择 Open Any Stacks
,在弹窗中可以轻松找到这个 rent 所在的代码,截图如下:
对 Http 的监控也是由于最近遇到了一个比较头疼的 dump 有感而发的,一个朋友的 dump 出现了 cpu 100% 的情况,我分析下来发现是程序在短时间内出现了大量的 Http Exception,进一步排查怀疑是 sdk 里面的异常,由于被吞了所以上层获取不到,也就找不到是第三方 sdk 哪里的代码块出的问题。
这里的找不到或者很难找到是在 WinDBG 场景下,其实借助 PerfView 还是比较好发现的,途径就是开启 System.Net.Http
ETW 事件,它内置了 14 个,太强大了,截图如下:
为了方便讲述,先上一段测试代码。
- internal class Program
- {
- static void Main(string[] args)
- {
- for (int i = 0; i < 5; i++)
- {
- GetString();
- }
-
- Console.ReadLine();
- }
-
- static async void GetString()
- {
- try
- {
- HttpClient client = new HttpClient();
-
- var html = await client.GetStringAsync("https://cnblogs1.com");
-
- Console.WriteLine(html);
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- }
这段代码会抛出异常,然后在 catch 中给吞掉了,因为抛了异常,就可以观察它的 RequestFailed
事件,然后找到对应的 RequestStart
事件,再观察它的调用栈即可。
接下来在 PerfView 中设置 *System.Net.Http:::@StacksEnabled=true
,再开启收集按钮,稍等片刻点击 Event
面板,搜集 Http
事件,截图如下:
从面板中可以清晰的观察到当前有 5
个请求失败,并且还带了关联的 ActivityID
, 接下来可以找 ActivityID=/#18920/1/29/
对应的 Request/Start
事件。
然后在 Time MSec
列上右键点击 Open Any Stacks
按钮,可以轻松的看到,那个 Request/Start
事件是 GetString()
方法触发的,截图如下:
总的来说,在 .NET 调试领域,让 PerfView 适当的配合 WinDbg,真的可以 如虎添翼 ,好了,本系列就先写到这里,感谢朋友们对本系列的持续关注。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。