如何测量DispatchQueue的背压
GCD队列背压测量优化方案
GCD本身确实留存了队列的任务运行相关数据,不需要完全依赖手动维护入出队block计数,以下是两种成熟的实现方案:
调试可视化场景方案
直接使用Xcode自带的Instruments工具:
- 选择GCD Counters模板,无需修改任何业务代码,即可实时展示所有自定义队列的待执行任务数、已执行任务数、执行耗时等核心指标
- 选择System Trace模板,可以生成完整的队列任务时间线,直观看到队列堆积的时间段、堆积原因,适合排查背压突增的问题
线上可埋点测量方案
如果需要在程序运行时采集背压数据做上报或者动态调度,可以用以下两种低侵入实现:
系统版本≥iOS10/macOS10.12
使用GCD公开的入队出队钩子能力:
- 给每个自定义队列通过
dispatch_queue_set_specific绑定一个原子计数变量,避免不同队列计数混淆 - 注册
dispatch_enqueue_hook和dispatch_dequeue_hook,全局拦截所有GCD任务的入队、出队事件,自动对应增减队列的原子计数 - 按需求的采样频率读取队列的计数即可,该方案对业务代码侵入为0,性能损耗可以忽略
兼容低系统版本
可以优化你现有的手动计数方案降低侵入性:
- 封装统一的异步/同步入队方法,替换所有业务代码中的原生
dispatch_async/dispatch_sync调用 - 封装方法内部使用
os_atomic原子变量做计数,避免加锁带来的额外性能损耗 - 所有队列的计数统一存储在全局字典中,通过队列标签做key区分,不需要给每个队列单独维护计数变量
背压阈值参考
拿到队列待执行任务数后,可以结合队列的QoS等级设置合理的背压判定阈值:
- 主队列、UI相关高优先级队列:待执行任务数≥5即可判定为存在背压
- 普通优先级队列:待执行任务数≥15即可判定为存在背压
- 后台低优先级队列:待执行任务数≥30即可判定为存在背压
注意:不要高频读取队列计数,建议采用秒级采样即可,避免计数读取操作本身影响程序性能。
内容的提问来源于stack exchange,提问作者Michael Ozeryansky
相关产品推荐
相关产品推荐

