MacOs前后台调度优先级观察

发布时间 2023-05-26 17:21:17作者: mooooonlight

场景构造

用swiftui写6个一摸一样的helloworld程序,间隔1s刷新展示一个不断递增的数字。分别将6个应用至于前台焦点(App_Foreground)、前台非焦点完全可见(App_Complete_Visiable)、半遮挡(App_Partially_Visiable)、被完全遮挡(App_Unvisiable)、最小化(App_Minimize)、隐藏(App_Hide)。如图所示,然后用instruments抓一段10s左右的trace:

注:隐藏应用指通过右键Dock栏点击隐藏这个动作。最小化即点击窗口左上角的最小化小圆圈。

优先级分布情况

打开每个进程观察它的Context Switch Points视图,里面可以看到每次线程上下文调度的优先级,依次对不同的可见状态下的应用进行分析。
注: 线程状态有好多种:Running、Runnable、Blocked等,这里先研究运行态的优先级和是否可见的关联关系,后文如果没有特殊说明,优先级的变化均指Running态的变化。

进程内的线程优先级的策略异同

这个简单的demo进程中包含很多个线程,不同的线程的优先级分布也是不一样的,各个进程包含的线程名及其个数罗列如下,可以看到,每个应用都有一个主线程、事件处理线程、workloop线程, 另外有n个start_wqthread线程,这个线程的用处暂无进一步进行研究:

线程名 App_Foreground App_Complete_Visiable App_Partially_Visiable App_Unvisiable App_Minimize App_Hide
Main Thread(UI线程) 1 1 1 1 1 1
com.apple.NSEventThread (事件处理) 1 1 1 1 1 1
dispatch_workloop_worker_thread(猜测定时器) 1 1 1 1 1 1
start_wqthread 4 2 3 2 2 2
以进程名命名的线程 1 1 1 1 1 1

线程切换running总次数和执行时间查看方法:

MainThread优先级比较

应用 优先级变化趋势 线程切换running总次数 总执行时间(ns)
App_Foreground trace记录中一开始主线程优先级为46,焦点点击到主线程后优先级变为稳定的47 4160 379980
App_Complete_Visiable 稳定46 960 92880
App_Partially_Visiable 稳定46 990 92790
App_Unvisiable 大部分优先级为4,少部分优先级为46 625 36460
App_Minimize 大部分优先级为4,少部分优先级为46 382 41740
App_Hide 大部分优先级为4,少部分优先级为46 283 38950

前台焦点进程的优先级变化趋势图(3.524s左右切换为焦点应用):

不可见进程的优先级变化趋势图:

com.apple.NSEventThread 线程的优先级比较

应用 优先级变化趋势 线程切换running总次数 总执行时间(ns)
App_Foreground 一开始线程优先级为46,切换为焦点后优先级变为稳定的47 4512 152360
App_Complete_Visiable 稳定46 692 27140
App_Partially_Visiable 稳定46 888 26750
App_Unvisiable 稳定46 12 274
App_Minimize 稳定46 4 203
App_Hide 稳定46 5 294

dispatch_workloop_worker_thread 线程的优先级比较

应用 优先级变化趋势 线程切换running总次数 总执行时间(ns)
App_Foreground 3%的46, 94%的37,2%的31 298 6050
App_Complete_Visiable 1次46,99%为37 63 2550
App_Partially_Visiable 12%的46, 52%的37,36%的31 26 1460
App_Unvisiable 4%的46, 96%的4 50 1600
App_Minimize 30%的46,70%的4 10 441
App_Hide 50%的46,50%的4 10 271

start_wqthread 线程的优先级比较

应用 优先级变化趋势 线程切换running总次数 总执行时间(ns)
App_Foreground 大部分37 1809 27622
App_Complete_Visiable 大部分37 233 4727
App_Partially_Visiable 大部分46,少部分37 21 611
App_Unvisiable 大部分46,1次4 6 145
App_Minimize 大部分46,少部分37 56 1170
App_Hide 大部分37、46,几次31 59 1363

明确的结论

这里的结论,前提是轻载,没有特意加压观察:

  • 焦点进程的主线程的优先级为47,非焦点可见进程(包括半遮挡)的主线程的优先级为46。不可见进程的主线程优先级会降低,大部分时间为最低的优先级4。
  • 焦点进程的事件处理线程的优先级为47, 其余进程的事件处理线程的优先级为46,均保持较高的优先级
  • workloop线程和start_wqthread线程(代表业务逻辑)大部分优先级低于UI和事件处理线程
  • 前台可见的进程执行的逻辑更多,运行时间更长,不可见和最小化进程包括UI、事件处理、业务逻辑都很少(Nap?)

遗留问题

  • 应用的线程模型的进一步研究,如workloop线程到底是不是定时器线程,start_wqthread线程的主要工作内容、以进程名字命名的线程名的主要功能等。
  • 线程状态的进一步研究,如Running、Runnable、Blocked的状态机模型是什么样的,网上没有找到对应的资料。
  • 重载下的线程优先级是否相比轻载会发生变化。
  • 可见应用除了优先级的区别,和大小核是否也有关联关系。
  • 不可见应用执行逻辑更少,是因为NAP机制?但是定时器的数字和前台基本一致。