PerfView专题 (第十二篇):对 C# 下的 SDK 类库进行监控(大结局)
一:背景
本篇是我们系列文章的最后一篇,前面的文章中大多是在 CLR Runtime 以及 OS 层面进行监控来发现各种可疑的程序问题,除了这两个层面,其实我们还可以对 SDK 中一些类进行洞察,比如说:
ArrayPool
Http
Socket
Task
更多资料可以看下:https://docs.microsoft.com/en-us/dotnet/core/diagnostics/well-known-event-providers
接下来就来个简单的抛砖引玉
二:如何洞察
1. ArrayPool 监控
之所以对 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 所在的代码,截图如下:

2. Http 监控
对 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() 方法触发的,截图如下:

3. 总结
总的来说,在 .NET 调试领域,让 PerfView 适当的配合 WinDbg,真的可以 如虎添翼 ,好了,本系列就先写到这里,感谢朋友们对本系列的持续关注。
PerfView专题 (第十二篇):对 C# 下的 SDK 类库进行监控(大结局)的更多相关文章
- 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)
解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...
- 第十二篇 SQL Server代理多服务器管理
本篇文章是SQL Server代理系列的第十二篇,详细内容请参考原文 在这一系列的上一篇,我们查看了维护计划,一个维护计划可能会创建多个作业,多个计划.你还简单地看了SSIS子系统,并查看了维护计划作 ...
- 第十二篇 Integration Services:高级日志记录
本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...
- Python之路【第十二篇】:JavaScrpt -暂无内容-待更新
Python之路[第十二篇]:JavaScrpt -暂无内容-待更新
- Python开发【第二十二篇】:Web框架之Django【进阶】
Python开发[第二十二篇]:Web框架之Django[进阶] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 ...
- 【译】第十二篇 Integration Services:高级日志记录
本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...
- 【译】第十二篇 SQL Server代理多服务器管理
本篇文章是SQL Server代理系列的第十二篇,详细内容请参考原文 在这一系列的上一篇,我们查看了维护计划,一个维护计划可能会创建多个作业,多个计划.你还简单地看了SSIS子系统,并查看了维护计划作 ...
- 专题开发十二:JEECG微云高速开发平台-基础用户权限
专题开发十二:JEECG微云高速开发平台-基础用户权限 11.3.4自己定义button权限 Jeecg中.眼下button权限设置,是通过对平台自己封装的button标签(<t:dgFun ...
- 跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探
SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如 ...
随机推荐
- Java 基础常见知识点&面试题总结(中),2022 最新版!| JavaGuide
你好,我是 Guide.秋招即将到来,我对 JavaGuide 的内容进行了重构完善,公众号同步一下最新更新,希望能够帮助你. 上篇:Java 基础常见知识点&面试题总结(上),2022 最新 ...
- python各版本下载
python2源码压缩包 Python-2.7.9.tgz Python-2.7.10.tgz Python-2.7.11.tgz Python-2.7.12.tgz Python-2.7.13. ...
- 【Golang】程序如何优雅的退出?
1. 背景 项目开发过程中,随着需求的迭代,代码的发布会频繁进行,在发布过程中,如何让程序做到优雅的退出? 为什么需要优雅的退出? 你的 http 服务,监听端口没有关闭,客户的请求发过来了,但处理了 ...
- 【Redis】事件驱动框架源码分析(多线程)
IO线程初始化 Redis在6.0版本中引入了多线程,提高IO请求处理效率. 在Redis Server启动函数main(server.c文件)中初始化服务之后,又调用了InitServerLast函 ...
- 【Srping】事务的执行原理(一)
在使用事务的时候需要添加@EnableTransactionManagement注解来开启事务,那么就从@EnableTransactionManagement入手查看一下事务的执行原理. @Enab ...
- iOS全埋点解决方案-APP和H5打通
前言 所谓的 APP 和 H5 打通,是指 H5 集成 JavaScript 数据采集 SDK 后,H5 触发的事件不直接同步给服务器,而是先发给 APP 端的数据采集 SDK,经过 APP 端数 ...
- SQL注入漏洞篇
一篇SQL注入漏洞汇总,更新中-- 如有缺陷 望大佬指正 SQL注入产生的原因? 当程序执行逻辑时没有对用户输入的参数做过滤处理,使参数直接与后台数据库产生逻辑交互,即SQL注入黑客就可以利用各种SQ ...
- 对vue响应式的理解
1.所谓数据响应式就是能够使数据变化可以被检测并对这种变化做出响应的机制. 2.MVVM框架要解决的一个核心问题是连接数据层和视图层,通过数据驱动应用,数据变化,视图更新,要做到这点的就需要对数据做响 ...
- java常见的面试题(一)
1.Collection 和 Collections 有什么区别? Collection 是一个集合接口(集合类的一个顶级接口).它提供了对集合对象进行基本操作的通用接口方法.Collection接口 ...
- 用python做个计算器不是轻轻松松吗~
计算器 Kivy是一个免费的开源Python库,可以快速轻松地开发高度交互的跨平台应用程序. 这里我将使用Python中的Kivy包来构建一个计算器GUI.(https://jq.qq.com/?_w ...