Matrix中WCBlockMonitorMgr 类详解以及流程

500 阅读8分钟

Matrix中WCBlockMonitorMgr 类详解以及流程


概述

WCBlockMonitorMgr 是微信开源性能监控框架 wechat-matrix 中用于监控 iOS/macOS 应用主线程卡顿(Block)和 CPU 高使用率的核心管理类。它通过监听主线程 RunLoop 状态,周期性采样调用栈,判断卡顿事件并触发回调,最终生成性能分析报告。该类设计了高效的监控线程,支持多种平台特性和动态配置,具备丰富的回调接口,方便集成和扩展。


目录


涉及到的相关模块

  • 依赖微信Matrix 框架内部多个模块,如:
    • WCMainThreadHandler(调用栈管理)
    • WCCPUHandler(CPU 使用率处理)
    • WCDumpInterface(卡顿报告生成)
    • WCPowerConsumeStackCollector(耗电堆栈采集)
    • WCBlockMonitorConfigHandler(配置管理)
    • WCFilterStackHandler(卡顿事件过滤)
    • 以及日志、设备信息等辅助模块。

CPU 频率测量

  • 仅在 ARM64 架构下实现,利用汇编指令循环计数结合 mach 时间戳,估算 CPU 频率。
  • 通过多次测量取中位数,保证稳定性。
  • 返回 CPU 频率的单位为 GHz。

全局静态变量说明

变量名说明
g_RunLoopTimeOut主线程 RunLoop 卡顿阈值,单位微秒,默认值由配置控制。
g_CheckPeriodTime检测周期时间,单位微秒,通常为阈值的一半。
g_CPUUsagePercentCPU 使用率阈值,超过该值认为 CPU 过高。
g_PerStackInterval单次调用栈采样间隔,单位微秒,默认约 50ms。
g_StackMaxCount单次调用栈最大采样帧数。
g_bSensitiveRunloopHangDetection是否启用敏感的 RunLoop 卡顿检测(iOS 11+)。
g_CurrentThreadCount当前线程数统计。
g_MainThreadHandle是否启用主线程调用栈采样。
g_MainThreadProfile是否启用主线程调用栈性能分析。
g_MainThreadCount一轮检测中采样调用栈的次数。
g_PointMainThreadArray当前主线程调用栈快照数组指针。
g_PointMainThreadRepeatCountArray调用栈重复计数数组。
g_PointMainThreadProfile主线程调用栈性能分析数据。
g_PointCPUHighThreadArrayCPU 使用率高线程调用栈快照数组。
g_PointCpuHighThreadCountCPU 高线程数量。
g_PointCpuHighThreadValueArrayCPU 高线程对应的 CPU 使用率数组。
g_thermalStateiOS 11+ 设备热状态。
g_tvRunRunLoop 最近运行时间戳。
g_bRunRunLoop 是否处于运行状态标志。
g_lastCheckTime上次检测时间戳。
g_bLaunchOver应用启动是否完成标志。
g_bBackgroundLaunch是否为后台启动。

类接口与属性

@interface WCBlockMonitorMgr : NSObject <WCPowerConsumeStackCollectorDelegate>

@property (nonatomic, weak) id<WCBlockMonitorDelegate> delegate;
@property (nonatomic, strong) WCBlockMonitorConfigHandler *monitorConfigHandler;

#if TARGET_OS_OSX
@property (nonatomic, strong) NSApplicationEvent *eventHandler;
#endif

+ (WCBlockMonitorMgr *)shareInstance;

- (void)resetConfiguration:(WCBlockMonitorConfiguration *)bmConfig;
- (void)start;
- (void)stop;

// iOS 特有:后台启动及挂起处理
- (void)handleBackgroundLaunch;
- (void)handleSuspend;

// CPU 监控控制
- (void)startTrackCPU;
- (void)stopTrackCPU;
- (BOOL)isBackgroundCPUTooSmall;

// RunLoop 阈值动态调整
- (BOOL)setRunloopThreshold:(useconds_t)threshold;
- (BOOL)lowerRunloopThreshold;
- (BOOL)recoverRunloopThreshold;

// 是否挂起所有线程
- (void)setShouldSuspendAllThreads:(BOOL)shouldSuspendAllThreads;

// 自定义卡顿报告生成
- (void)generateLiveReportWithDumpType:(EDumpType)dumpType withReason:(NSString *)reason selfDefinedPath:(BOOL)bSelfDefined;

// 获取当前卡顿报告自定义用户信息
- (NSDictionary *)getUserInfoForCurrentDumpForDumpType:(EDumpType)dumpType;

#if TARGET_OS_OSX
+ (void)signalEventStart;
+ (void)signalEventEnd;
#endif

@end

核心功能详解

单例获取与初始化

  • 使用 GCD dispatch_once 保证单例线程安全。
  • 初始化时创建异步串行队列,设置默认停止状态。
  • 释放时释放 RunLoop 观察者,移除通知监听,释放调用栈缓存。

配置管理

  • 通过 resetConfiguration: 方法注入配置对象 WCBlockMonitorConfiguration
  • 配置包括卡顿阈值、CPU 使用率阈值、采样间隔、是否打印日志、是否启用耗电堆栈采集等。
  • 配置会影响内部静态变量和监控参数。

启动与停止监控

  • start 方法初始化参数,添加 RunLoop 观察者,创建监控线程并启动。
  • 监听应用生命周期通知(iOS),如进入后台、激活、终止等,调整监控策略。
  • stop 方法停止监控线程,移除 RunLoop 观察者,等待监控线程退出。

RunLoop 观察者管理

  • 通过 CFRunLoopObserverCreate 创建两个观察者,分别监听 RunLoop 入口和退出阶段。
  • 观察者回调更新全局运行状态 g_bRun 和时间戳 g_tvRun
  • 支持普通模式和初始化模式(iOS UIInitializationRunLoopMode)。
  • 在敏感模式下,RunLoop 即将等待时检测卡顿。

监控线程主循环

  • 监控线程执行 threadProc 方法,循环检测卡顿。
  • 先睡眠启动延迟,避免启动时干扰。
  • 每轮调用 check 判断卡顿类型。
  • 根据检测结果决定是否采样调用栈和生成报告。
  • 通过代理回调通知外部监控状态和报告文件路径。
  • 线程安全管理调用栈数据和状态。

卡顿检测逻辑

  • 判断 RunLoop 是否超时(当前时间 - 最近一次 RunLoop 活动时间 > 阈值)。
  • 判断应用是否处于后台,区别不同卡顿类型。
  • 判断 CPU 使用率是否超过阈值,结合耗电堆栈采集器状态决定是否生成 CPU 卡顿报告。
  • 打印 CPU 和内存使用情况,超过阈值触发回调。
  • 敏感模式下额外检测 RunLoop 挂起时长。

调用栈采样

  • 根据配置的采样间隔,周期性采样主线程调用栈。
  • 采样时调用 WCGetMainThreadUtil 获取当前调用栈,存入 WCMainThreadHandler 管理的循环队列。
  • 采样次数和间隔根据卡顿阈值动态调整。

卡顿事件过滤

  • 通过比较当前调用栈与上一次调用栈,判断是否重复。
  • 采用退火算法动态调整检测间隔,避免重复上报。
  • 通过 WCFilterStackHandler 控制每日上报次数,防止过度报警。
  • 过滤无效(调用栈长度过短)和重复卡顿事件。

卡顿报告生成

  • 通过 WCDumpInterface 生成卡顿报告文件,支持挂起所有线程确保快照一致。
  • 支持启动阶段卡顿特殊处理,保存启动卡顿记录。
  • 支持异步写文件和自定义路径。
  • 生成报告时通过代理回调通知外部。

后台与前台状态处理

  • 监听 UIApplication 生命周期通知,更新当前应用状态。
  • 后台启动时清理历史卡顿文件,避免误报。
  • 前台激活时重置启动标志,允许正常检测。
  • 支持后台启动和挂起事件的特殊处理。

CPU 和内存使用监控

  • 周期性采集应用和设备 CPU 使用率。
  • 通过 WCCPUHandler 统计 CPU 平均值,判断是否过高。
  • 采集内存占用,超过阈值触发回调。
  • 支持打印设备热状态(iOS 11+)。
  • 支持耗电堆栈采集,分析高耗电代码路径。

热状态监听

  • iOS 11+ 监听 NSProcessInfoThermalStateDidChangeNotification
  • 设备热状态升高时回调代理,方便开发者优化性能。

动态阈值调整

  • 支持动态调整 RunLoop 卡顿阈值,范围限制在 400ms 到 2s。
  • 阈值调整后更新检测周期和采样次数。
  • 支持降低阈值以提高检测灵敏度,或恢复默认阈值。

耗电堆栈采集委托

  • 实现 WCPowerConsumeStackCollectorDelegate,异步保存耗电堆栈报告。
  • 生成 JSON 格式报告,保存到指定路径。

代理回调接口说明

@protocol WCBlockMonitorDelegate <NSObject>

@required
- (void)onBlockMonitor:(WCBlockMonitorMgr *)bmMgr enterNextCheckWithDumpType:(EDumpType)dumpType;
- (void)onBlockMonitor:(WCBlockMonitorMgr *)bmMgr beginDump:(EDumpType)dumpType blockTime:(uint64_t)blockTime runloopThreshold:(useconds_t)runloopThreshold;
- (void)onBlockMonitor:(WCBlockMonitorMgr *)bmMgr dumpType:(EDumpType)dumpType filter:(EFilterType)filterType;
- (void)onBlockMonitor:(WCBlockMonitorMgr *)bmMgr getDumpFile:(NSString *)dumpFile withDumpType:(EDumpType)dumpType;
- (NSDictionary *)onBlockMonitor:(WCBlockMonitorMgr *)bmMgr getCustomUserInfoForDumpType:(EDumpType)dumpType;
- (void)onBlockMonitorCurrentCPUTooHigh:(WCBlockMonitorMgr *)bmMgr;
- (void)onBlockMonitorIntervalCPUTooHigh:(WCBlockMonitorMgr *)bmMgr;
- (void)onBlockMonitorThermalStateElevated:(WCBlockMonitorMgr *)bmMgr;
- (void)onBlockMonitorMainThreadBlock:(WCBlockMonitorMgr *)bmMgr;
- (void)onBlockMonitorMemoryExcessive:(WCBlockMonitorMgr *)bmMgr;
- (void)onBlockMonitor:(WCBlockMonitorMgr *)bmMgr runloopHangDetected:(uint64_t)duration;

@end
  • 通过这些方法,外部可以获得卡顿检测状态、报告生成通知、CPU 和内存异常警告、设备热状态变化等信息。
  • 方便业务侧根据性能异常做日志上报、用户提示或自动恢复措施。

辅助工具方法

  • + (unsigned long long)diffTime:(struct timeval *)tvStart endTime:(struct timeval *)tvEnd;
    计算两个时间戳之间的微秒差值。

  • 多个全局函数用于提供调用栈快照和性能分析数据给外部模块。

  • 支持 macOS 平台的事件信号通知。


大致流程

Mermaid Chart - Create complex, visual diagrams with text. A smarter way of creating diagrams.-2025-06-24-112321.png

总结

WCBlockMonitorMgr 是微信 Matrix 性能监控框架中极其重要的核心类,负责主线程卡顿检测和 CPU 监控。它设计了完善的监控流程和机制,具备丰富的配置选项和回调接口,支持 iOS/macOS 多平台,适用于复杂的性能监控场景。通过合理的采样、过滤和报告机制,能够有效捕获应用运行中的卡顿和高 CPU 使用问题,为性能优化提供有力支持。


参考:

matrix-wechat