当前位置:网站首页>如何获取GC(垃圾回收器)的STW(暂停)时间?
如何获取GC(垃圾回收器)的STW(暂停)时间?
2022-07-05 09:36:00 【dotNET跨平台】
前言
在现代的容器化和微服务应用中,因为分布式的环境和错综复杂的调用关系,APM(Application Performance Monitoring 应用性能监控)显得尤为重要,它通过采集应用程序各种指标和请求链路,让你知道系统当前的状态和值得优化的点,另外能帮助你发现应用程序的异常,帮助你更方便的定位问题。
对于.NET这样带GC(Garbage Collector 垃圾回收器)的平台来说,GC的指标也尤为重要,采集可以帮助我们分析内存泄漏、优化系统性能等等。在公司内部已经可以采集比较全面的.NET GC指标,如下图所示。
在绝大多数场景它能满足要求,但是如果遇到某时某刻P95延时突然增大,异步任务突然超时,我们想排查这些异常是否因为GC的STW Time(Stop The World Time 指GC运行过程中所有线程被挂起的时间)过长导致的,就没有办法了,因为目前没有采集这些指标。
所以本文就带大家了解一下,如何采集.NET GC STW Time。
方法
如.NET内存性能分析指南中提到的一样,.NET Runtime在运行过程中会发布很多事件,这些事件代表了当前Runtime的运行状态,同样GC在运行过程中也会发布很多事件,我们可以使用PerfView工具来收集这样的一些事件。下面是WorkStationGC发生GC时的一个事件序列。
Microsoft-Windows-DotNETRuntime/GC/SuspendEEStart //开始暂停托管线程运行Microsoft-Windows-DotNETRuntime/GC/SuspendEEStop //暂停托管线程完成Microsoft-Windows-DotNETRuntime/GC/Start // GC开始回收Microsoft-Windows-DotNETRuntime/GC/Stop // GC回收结束Microsoft-Windows-DotNETRuntime/GC/RestartEEStart //恢复之前暂停的托管线程Microsoft-Windows-DotNETRuntime/GC/RestartEEStop //恢复托管线程运行完成PS: 所有的事件都可以在.NET文档官方中找到,非常的全面。
而SuspendEEStart(暂停托管线程运行)到RestartEEStop(恢复托管线程运行完成)中经过的时间就是STW Time,我们只需要记录这两个事件的差值,就可以知道本次GC STW的时间有多长。
BGC的过程比WorkStationGC复杂的很多,但是一样是测量这两个事件花费的时间来采集STW Time,本文不做过多介绍。
使用EventSource采集
那么我们知道通过计算哪两个指标的差值来获得STW时间,那么应该如何通过代码来采集呢?
这里就需要知道EventSource和EventListener两个类,顾名思义我们可以通过EventSource来发布事件,使用EventListener来监听事件,在本文中我们也主要使用EventListener来收集GC事件,对于这EventSource类的使用大家可以看下面给出的微软文档链接,这里不做过多介绍。
EventSource
EventListener
我们来看一看如何使用EventListener类监听GC事件,代码如下所示:
using System.Diagnostics.Tracing;
// 开启GC事件监听 var gc = new GcStwMetricsCollector();
// 创建一些对象 var array = Enumerable.Range(0, 1000).Select(s => (decimal)s).ToArray();
// 手动执行GC GC.Collect();
Console.ReadLine();
public class GcStwMetricsCollector : EventListener {
// GC关键字
private const int GC_KEYWORD = 0x0000001;
// 我们要关注的GC事件
private const int GCSuspendEEBegin = 9;
private const int GCRestartEEEnd = 3;
private EventSource? _eventSource;
public void Stop()
{
if (_eventSource == null)
return;
DisableEvents(_eventSource);
}
protected override void OnEventSourceCreated(EventSource eventSource)
{
_eventSource = eventSource;
// GC 事件在 Microsoft-Windows-DotNETRuntime 名称空间下 if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime"))
{
// 启用事件,事件级别为Informational, 只监听GC事件
EnableEvents(eventSource, EventLevel.Informational, (EventKeywords) (GC_KEYWORD));
}
}
private long _currentStwStartTime = 0;
protected override void OnEventWritten(EventWrittenEventArgs e)
{
switch (e.EventId)
{
// 冻结托管线程开始,记录当前时间
case GCSuspendEEBegin:
_currentStwStartTime = e.TimeStamp.Ticks;
break;
// 恢复托管线程结束,计算当前时间与冻结托管线程开始时间的差值
case GCRestartEEEnd:
if (_currentStwStartTime > 0)
{
var ms = TimeSpan.FromTicks(e.TimeStamp.Ticks - _currentStwStartTime).TotalMilliseconds;
_currentStwStartTime = 0;
// 输出结果
Console.WriteLine($"STW: {ms}ms");
}
break;
}
}
}运行结果:
STW: 0.2568ms至于GC事件对应的枚举值,大家可以在我上文中给出的文档中找到。
.NET7新API
在实现这个需求时,我注意到.NET7有一个新的issue,直接提供了一个API,让我们可以获取到总的GC STW Time,我把重点的信息摘抄和翻译了一下。
背景和动机
今天我们已经在GetGCMemoryInfo 公开了获取GC处理时间和暂停时间的百分比值的API。
具体来说是通过GCMemoryInfo的PauseTimePercentage字段。
这个很有用,但是如果我只想要一个分子(即:程序运行以来总的GC暂停时间)。现在没有办法获取到。
API 提案
我建议在System.GC上添加一个下面这样的API:
TimeSpan System.GC.GetTotalPauseDuration()它会返回GC总的暂停时间。
API 使用
TimeSpan start = System.GC.GetTotalPauseDuration();// ... Perform some work ...TimeSpan end= System.GC.GetTotalPauseDuration();
Console.WriteLine(end - start + " was spent pausing in GC");我看到这个API已经和最新的.NET7预览版一起发布,我们下载最新的.NET7 SDK,然后把项目改成.NET7,来试试这个API,代码如下所示: using System.Diagnostics.Tracing;
// 开启GC事件监听 var gc = new GcStwMetricsCollector();
// 创建一些对象 var array = Enumerable.Range(0, 1000).Select(s => (decimal)s).ToArray();
// 手动执行GC GC.Collect();
Console.WriteLine($"API STW:{GC.GetTotalPauseDuration().TotalMilliseconds}ms");
Console.ReadLine();// 省略上文中一样的代码运行结果: API STW: 0.223ms
Event STW: 0.296msAPI统计的应该会更加准确,我们通过事件来获取多多少少有一点额外的开销,不过误差在可接受的范围内。
总结
上文中提到了两种方式来获取.NET GC STW Time,我们只需要稍加改造,就可以将STW监控的功能加入APM中,如下图表就是本地测试时采集的一些数据。
当然通过EventListener还可以实现更多的APM信息的采集,大家有兴趣也可以研究看看。
本文代码链接Github: https://github.com/InCerryGit/BlogCodes/tree/main/Get-GC-STW-Time
往期文章:
.NET性能优化-推荐使用Collections.Pooled(补充)
.NET性能优化-使用ValueStringBuilder拼接字符串
.NET性能优化-使用结构体替代类
边栏推荐
- 【饿了么动态表格】
- First understanding of structure
- 【el-table如何禁用】
- How do enterprises choose the appropriate three-level distribution system?
- The most comprehensive promotion strategy: online and offline promotion methods of E-commerce mall
- What are the advantages of the live teaching system to improve learning quickly?
- MySQL does not take effect in sorting string types
- [NTIRE 2022]Residual Local Feature Network for Efficient Super-Resolution
- How to choose the right chain management software?
- Mobile heterogeneous computing technology GPU OpenCL programming (Advanced)
猜你喜欢

Roll up, break through 35 year old anxiety, and animate the CPU to record the function call process

How to implement complex SQL such as distributed database sub query and join?

基于宽表的数据建模应用

A keepalived high availability accident made me learn it again

H.265编码原理入门

Oracle combines multiple rows of data into one row of data

TDengine ×英特尔边缘洞见软件包 加速传统行业的数字化转型

Unity SKFramework框架(二十三)、MiniMap 小地图工具

Develop and implement movie recommendation applet based on wechat cloud

How to choose the right chain management software?
随机推荐
美图炒币半年亏了3个亿,华为被曝在俄罗斯扩招,AlphaGo的同类又刷爆一种棋,今日更多大新闻在此...
Cross process communication Aidl
Tutorial on building a framework for middle office business system
oracle 多行数据合并成一行数据
微信小程序获取住户地区信息
22-07-04 Xi'an Shanghao housing project experience summary (01)
From "chemist" to developer, from Oracle to tdengine, two important choices in my life
Application of data modeling based on wide table
卷起来,突破35岁焦虑,动画演示CPU记录函数调用过程
分布式数据库下子查询和 Join 等复杂 SQL 如何实现?
如何正确的评测视频画质
How to choose the right chain management software?
从“化学家”到开发者,从甲骨文到 TDengine,我人生的两次重要抉择
[team PK competition] the task of this week has been opened | question answering challenge to consolidate the knowledge of commodity details
Unity SKFramework框架(二十三)、MiniMap 小地图工具
揭秘百度智能测试在测试自动执行领域实践
Why do offline stores need cashier software?
OpenGL - Lighting
Gradientdrawable get a single color
mysql安装配置以及创建数据库和表