根据apple官方文档[1],苹果的iOS、iPadOS、Mac Catalyst、macOS、tvOS、visionOS、watchOS有一个任务QoS的接口,可以设置task的类别:QoS(Quality of Service,服务质量)类用于对提交到 DispatchQueue 上的任务进行分级,用来描述这些任务对应用的重要性。通过为任务指定合适的 QoS,开发者可以明确告诉系统该任务的优先级。系统在进行任务调度时,会优先调度 QoS 更高的任务。
需要注意的是,高 QoS 的任务通常会更快完成,并且能够获得更多的系统资源,但这也意味着更高的能耗。相反,低 QoS 的任务虽然执行较慢,但对系统资源和电量的消耗也更低。
因此,为应用中的不同任务合理、准确地指定 QoS 类,有助于在保证应用响应速度的同时,提高整体的能效表现。
iOS / macOS 中常用的 QoS(Quality of Service)类一共有 5 个,按优先级从高到低排列如下:
1. userInteractive(最高优先级)
适用场景
直接影响 UI 的任务
必须马上完成,否则用户能立刻感知到卡顿的操作
典型例子
UI 渲染、动画计算
主线程需要立刻用到的结果
手势响应相关的计算
特点
使用建议👉 只用于“现在不跑,界面就卡”的任务,数量要尽量少。
2. userInitiated
适用场景
用户主动触发,并且在等待结果的任务
不做完用户就无法继续下一步操作
典型例子
打开页面时的数据加载
用户点击按钮后触发的计算
文档、图片的同步加载和解析
特点
使用建议👉 大多数“用户点了就等结果”的不在主线程上执行,但其结果会被主线程使用的任务,优先选这个。
3. default
适用场景
典型例子
特点
使用建议👉 不确定用哪个时,default 是安全选择。
4. utility
适用场景
需要较长时间执行
用户能感知到任务在进行,但不急着完成
典型例子
特点
使用建议👉 “慢慢跑没关系,但别影响前台体验”的任务。
5. background(最低优先级)
适用场景
典型例子
特点
使用建议👉 只要不影响用户体验,能放后台就放后台。
一个简单的记忆口诀
UI 卡不卡 → userInteractive用户点了在等 → userInitiated不确定 → default慢慢来 → utility用户看不见 → background
它对Linux的启示是什么呢?
它这个实际上是比Linux调度器接口更高一个层次的抽象。Linux可以调整nice、EEVDF里面调整time slice,或者设置调度算法为SCHED_FIFO、RR、DEADLINE,设置uclamp等,但是都是非常底层的接口,并不是用户层面的抽象。所以Linux潜在的有如下需求:
为应用提供一个高层次的 API,使开发者在使用时不需要了解调度器的具体配置细节。
Qais Yousef在2025年12月东京的LPC上领导了这个讨论[2],他建议把QoS抽象接口与Linux调度器底层接口进行一定的映射,这样就沿用了Linux本身的代码:
他举了一个栗子,比如240HZ和30HZ的时候,分别怎么配置这种映射:
在具体如何部署这些QoS hint,他提出能否通过配置文件而不用强制代码调用API,比如:
所以这需要我们开发SchedQoS的库和中间件。QoS 的语义被限制在一个很小、可控的层里(SchedQoS)。这样一来,内核侧的实现可以更灵活,回滚 / 重构成本大幅降低,同时也更容易在内核里做 QoS 相关的实验。
说实话,这些愿景听起来非常美好!!!让我们拭目以待它的进展!!!
文献:
[1] https://developer.apple.com/documentation/dispatch/dispatchqos
[2]https://lpc.events/event/19/contributions/2089/attachments/1797/3877/Userspace%20Assisted%20Scheduling%20via%20Sched%20QoS.pdf