苹果7p找不到设备管理和描述文件


苹果7p找不到设备管理和描述文件  

引言

在启动优化过程中,我们经常通过增加并发的方式来减轻主线程的负载压力。在iOS开发中,(Grand Central Dispatch)是最常用的并发编程框架。是否增加并发一定是启动优化的良策?开发者该如何选择队列的优先级?本文将结合飞书启动优化的实践,分享选取队列的最佳实践,并给出针对低端机的启动优化思路。

一、低端机的特性

通过Instruments的App Launch功能,我们可以观察到App启动时的线程状态、Time Profiler等信息。我们发现不同设备在启动时的表现存在显著差异。

以iPhone 7p(低端)和iPhone 12(高端)为例,它们在CPU参数上有所区别。在启动飞书时,我们通过Instruments观察两个设备的线程状态,发现iPhone 7p上主线程Preempted和Runnable状态的占比高达21%,而iPhone 12上这一比例仅占1%。这说明对低端机来说,CPU已经成为启动的瓶颈,增加并发已不是一个万能的启动优化措施。

二、 queue对主线程的抢占评测

为了评估“减少其他线程对主线程的抢占”是否是一个可行的优化思路,我们首先需要了解主线程被抢占的程度。为此,我们设计了一系列Demo实验,通过不同的队列QoS(质量服务)设置,观察主线程被抢占的情况。

实验结果显示,不指定QoS时,自行创建的 queue的QoS默认为User-Initiated。User-Initiated及以上优先级的队列会对主线程产生严重抢占现象,而Utility和Background几乎不会抢占主线程。

我们也发现pthread_create创建的线程存在类似的抢占现象。

三、QoS和Priority

了解QoS(质量服务)和线程priority的关系对于优化至关重要。苹果的官方文档为每种任务提供了推荐的QoS,而线程的priority会随着执行动态调整。主线程的priority在运行开始时是QoS User-Interactive 对应的47,但随着运行会出现下降的情况。为了防止计算密集型线程垄断资源,Mach scheduler会实时调整各个线程的priority。

四、优化落地

通过Demo实验,我们产生了优化思路:在飞书中,大量异步队列的QoS 是 User-Initiated,尽管这一QoS 低于主线程的 User-Interactive,但依然可能对主线程造成抢占。如果将异步队列的 QoS 调低到 Utility,是否可以优先保障主线程执行,让首屏更早展现出来?

经过实验验证,这一思路在飞书上存在优化空间。但如何兼顾首屏、消息列表首刷等多个指标呢?我们需要梳理出哪些异步操作是首刷依赖的,确保这些队列的 QoS 设置合理。我们通过不断测试、阅读代码,梳理出首屏展示队列,并在线下和线上验证了关键指标的优化收益。后来,我们还开发了线下工具,自动生成依赖的首刷 队列。

五、效果分析

这一优化策略在线上产生了显著的效果:启动首屏展现时间优化了100ms,消息列表首刷时间优化了1500ms。通过调整异步线程的 QoS,启动期间主线程 CPU 抢占现象有明显降低。更多计算资源集中到主线程,使得首屏展示速度明显加快。通过对消息列表首刷依赖的任务的分析,我们调低了无关线程的 QoS,加速了首刷依赖的任务的执行。

“增加并发”在一定范围内可以作为启动优化的方案,但在低端机上,CPU 已经成为瓶颈,并发时异步线程对主线程的抢占也需要引起重视。提供了四种QoS 供开发者使用,开发者创建的 队列,默认的 QoS 实际为 User-Initiated。在启动期间(或任何耗时敏感期间),与启动无直接关系的 queue 应该主动设置为 Utility 或 Background,减少对主线程的抢占。通过飞书上落地优化实践表明,对线程或 queue 调整 QoS 能在不改变启动业务逻辑的情况下取得显著收益。

七、加入我们

字节跳动APM中台致力于提升产品的性能和稳定性表现,技术栈覆盖iOS/Android/Server/Web等。

  苹果7p找不到设备管理和描述文件