关于 ios-launch-performance
ios-launch-performance 是用于审查 iOS 启动路径的技能,关注从启动请求到首个可见界面及早期响应。它帮助开发者区分启动阶段、定位阻塞或非必要工作,并验证针对性改动。
主要功能
- 01分类启动场景与阶段
- 02检查启动任务和依赖
- 03查找隐藏的预先初始化
- 04提出针对性启动改动
- 05制定测量与验证方案
适用场景
- 01调查应用启动缓慢或退化
- 02审查 AppDelegate 与 SwiftUI 启动代码
- 03评估启动路径上的 SDK 初始化
- 04规划启动性能测量
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ livsy90/ ios-performance-agent-skills --skill ios-launch-performance安装后在 Claude Code 中输入/ios-launch-performance确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/appdelegate-scenedelegate-and-first-frame.mdlaunch-orchestration-and-dependency-graph.mdlaunch-taxonomy-and-targets.mdlinking-strategy.mdmetrics-instruments-xctest-metrickit.mdpre-main-dyld-and-static-initializers.mdswiftui-app-launch.mdthird-party-sdks-at-launch.md详细介绍
iOS 启动性能
使用此技能检查从应用启动请求到首个可见 UI 和早期响应能力的整个路径。
重点关注以下阶段的工作:
main之前- UIKit 或 SwiftUI 启动期间
UIApplicationDelegate、UISceneDelegate或 SwiftUIApp中- 根 UI 创建期间
- 首个可见帧出现之前
- 首次有意义的交互发生之前
- 启动后的早期工作(仍会影响用户感知的就绪状态)
这不是通用的 iOS 性能技能。仅在问题与启动有关,或代码运行于启动路径上时使用。
核心模型
将启动视为包含多个独立阶段的流水线:
- 进程创建和系统准备
- dyld 加载、绑定、修复、运行时注册和静态初始化
- UIKit 或 SwiftUI 运行时启动
- 在
UIApplicationDelegate、UISceneDelegate或 SwiftUIApp中进行应用级初始化 - 启动编排和依赖项设置
- 根 UI 构建、布局、绘制和首帧提交
- 影响响应能力的启动后早期工作
- 后续特定功能或维护工作
不要盲目优化。先确定哪个阶段开销较大,再针对该阶段的工作提出移动、移除、延迟加载、并行化、串行化或测量方面的改进建议。
何时使用此技能
当任务涉及以下内容时,使用此技能:
- 应用启动缓慢
- 启动性能回退
- 冷启动、温启动或预热启动
- 恢复与启动的混淆
- 首帧就绪
- 启动后的早期响应能力
main之前的工作或 dyld 工作- Objective-C
+load、+initialize、构造函数或静态初始化 - AppDelegate 或 SceneDelegate 启动工作
- SwiftUI
@main App、WindowGroup、根视图设置或环境注入 - 启动期间的依赖容器设置
- 启动编排器或有序启动步骤
- 启动期间的第三方 SDK 初始化
- 怀疑启动开销时的框架链接策略
- 来自 Instruments、XCTest、MetricKit 或 Xcode Organizer 的启动指标
以下情况不要使用此技能:
- 通用滚动性能
- 与启动无关的内存泄漏
- 与首帧无关的渲染优化
- 启动之外的网络性能
- 广泛的架构审查,除非架构会影响启动路径
启动场景分类
给出建议前,先确定测量的是哪种情况:
- 冷启动:应用进程不在内存中,且与启动相关的状态基本未预热。
- 温启动:应用仍会启动新进程,但部分系统状态、缓存或页面可能已预热。
- 预热启动:用户明确打开应用前,系统可能已准备好启动路径中的一部分。
- 恢复/返回已运行应用:应用进程已存在,并从后台或挂起状态返回。
- 首次安装/首次运行/更新后启动:启动时包含额外设置,例如迁移、缓存创建、权限、账户/引导工作或特定版本的设置。
- 未知:测量设置未明确区分上述情况。
不要将冷启动、温启动、预热启动、首次运行启动、更新后启动和恢复视为同一项指标进行比较。
除非任务明确询问切换到前台的延迟,否则恢复不属于完整的启动调查。
调查工作流
1. 定位启动路径
找出首帧出现之前或首次有意义的交互发生之前执行的代码。
检查:
- 应用代理
- 场景代理
- SwiftUI
App - 根场景构建
- 根视图/模型创建
- 依赖容器设置
- 全局/静态初始化
- 启动编排器
- SDK 启动
- 已链接框架的初始化
- 首屏路由和状态恢复
2. 对慢速阶段进行分类
在建议修复方案前,先对可能的阶段进行分类:
- dyld/主程序运行前
- Objective-C 或 Swift 运行时/静态初始化
- App 委托启动
- 场景委托启动
- SwiftUI 应用/根视图初始化
- 启动编排或依赖项设置
- 根界面构建和首帧渲染
- 启动后的早期响应能力
- 测量结果存在歧义
如果现有证据不足以对阶段进行分类,请明确说明,并建议下一步的测量方式。
3. 按必要性对启动任务进行分类
对每项启动任务进行分类:
- 首帧显示前必须完成
- 首次交互前必须完成
- 启动后不久需要
- 仅在认证/会话状态明确后需要
- 仅供后续功能使用
- 后台维护
除非出于正确性原因,否则首帧或首次交互前不必完成的工作不应阻塞启动。
4. 梳理依赖关系
如果启动包含有序步骤、SDK 设置调用、服务注册或启动编排器,请明确指出:
- 哪些步骤对于显示首个可见界面确实必需
- 哪些步骤必须在首次有意义的交互前完成
- 哪些步骤可以独立运行
- 哪些步骤必须保持顺序
- 哪些步骤会触及主线程或共享可变状态
- 哪些故障必须阻塞启动
- 哪条依赖链构成最长关键路径
将注释、脆弱的顺序依赖和隐性经验知识视为风险。优先明确声明依赖关系,而不是依赖调用顺序。
5. 查找隐藏的急切执行工作
检查是否有启动工作隐藏在以下位置:
- Objective-C
+load - Objective-C
+initialize - C/C++ 构造函数
- 带构造函数的 C++ 全局对象
- Swift 全局变量或静态属性
- 急切初始化的单例
- 依赖关系图构建
- SDK 自动注册
- 动态框架启动
- 同步文件 I/O
- 打开数据库或执行迁移
- 大量 Keychain 操作
- 网络请求或远程配置
- 大型解码/解析操作
- 主线程上的阻塞锁、信号量、调度组或同步等待
在测量结果证明并非如此之前,应将隐藏的初始化视为启动关键工作。
6. 建议有针对性的改动
优先选择能直接缩短启动路径或解除其阻塞的改动:
- 移除不必要的启动工作
- 延迟加载特定功能的服务
- 将非关键工作推迟到界面可见或首次交互之后
- 将启动关键状态与次要应用状态分开
- 明确声明启动依赖关系
- 将隐藏的静态初始化改为显式初始化或延迟初始化
- 仅在安全且有效时,将阻塞工作移出主线程
- 只有在审查过依赖关系、共享状态、隔离性和故障处理方式后,才采用有界并行
- 只有在证据表明问题出在主程序运行前阶段或 dyld 开销时,才审查链接策略
- 缩小首个可用界面的范围,而不是在显示前初始化整个应用依赖关系图
除非无法通过较小改动安全地优化启动路径,否则不要建议进行大范围重写。
7. 要求验证
每项建议都应包含验证方案。
使用:
- Instruments App Launch 进行阶段级诊断
- Time Profiler 分析 CPU 密集型启动路径
- 怀疑存在主程序运行前工作时,使用与 dyld 相关的工具或日志
- 使用
os_signpost或同类标记标注应用特定的启动阶段 - 使用 XCTest 启动指标进行可重复的本地或 CI 回归检查
- 使用 MetricKit 或 Xcode Organizer 检查生产环境中的分发版本
优先使用接近发布版本的构建、真实设备、稳定的测试数据、多次运行,以及较旧的受支持硬件。
高价值决策规则
- 将首个可见帧大约 400 ms 的目标视为激进的用户体验目标,而非看门狗阈值,也不是仅适用于 main 函数运行前的预算。
- 不要默认归咎于 dyld。启动缓慢可能源于 main 函数运行前的工作、应用初始化、启动编排、根 UI 创建、首帧渲染、同步 I/O 或启动后早期阻塞。
- 在测量证明确实无碍之前,将
+load、构造函数和带有副作用的静态初始化视为启动关键操作。 - 优先采用显式设置、延迟初始化或限定作用域的一次性初始化,而非隐藏在加载时钩子中的工作。
- 不要将
+initialize描述为通用解决方案。它可能对某些旧版 Objective-C 代码有帮助,但在现代代码中,显式初始化或延迟初始化通常更清晰。 - 不要建议将所有模块都改为静态链接。应考虑启动成本、构建时间、二进制大小、重复符号、资源打包、SDK 分发、调试和可合并库等因素。
- 不要设置随意的框架数量限制。更多动态框架可能会增加启动工作,但实际成本必须经过测量。
- 在依赖关系、共享状态、Actor 隔离、主线程要求和失败行为明确之前,不要并行执行启动步骤。
- 除非已证明代码安全、耗时有界且启动必须等待这些工作完成,否则不要在等待并行启动工作时阻塞主线程。
- 即使不安全的并行化改善了本地基准测试,也要将其视为正确性风险。
- 优化最长的必需依赖链,而不只是最大的单项启动步骤。
- 不要假设在主队列上异步排队的工作一定会在首帧之后运行。
- 不要假设 SwiftUI
.task一定在渲染后运行或不会造成影响。它是与生命周期绑定的异步工作,仍可能影响早期响应能力。 - 评估启动性能时,不要依赖 Debug 构建、仅在模拟器上运行的结果或单台新款设备。
- 不要仅凭生产环境的启动耗时直方图来定位本地瓶颈。应使用它们来确定优先级并验证趋势。
代码审查清单
审查与启动相关的代码时,先检查以下方面。
main 函数运行前及运行时初始化
留意 +load、构造函数、C++ 全局构造函数、耗时较长的 Swift 全局变量/静态变量、急切的运行时钩子、Objective-C 类别繁多的模块,以及在启动时会执行初始化器的动态框架。
如果此方面与当前问题相关,请阅读 references/pre-main-dyld-and-static-initializers.md。
启动编排和依赖关系图
留意耗时较长的有序启动序列、隐式依赖、通过启动注释表达的顺序要求、同步构建的依赖容器、不安全的并行化、阻塞式等待、不明确的失败行为,以及假设整个应用依赖图已就绪的首屏代码。
如果此方面与当前问题相关,请阅读 references/launch-orchestration-and-dependency-graph.md。
AppDelegate、SceneDelegate 和首帧
留意同步依赖设置、无条件初始化 SDK、打开或迁移数据库、访问钥匙串、同步网络请求、繁重的根视图模型构建、重复的应用/场景设置,以及耗时较长的首屏渲染。
如果此方面与当前问题相关,请阅读 references/appdelegate-scenedelegate-and-first-frame.md。
SwiftUI App 启动
留意 App.init、根 Scene 构造、根视图初始化、急切创建的可观察模型、环境注入、.task、.onAppear、scenePhase 和 @UIApplicationDelegateAdaptor 中的繁重工作。
如果此方面与当前问题相关,请阅读 references/swiftui-app-launch.md。
第三方 SDK
启动期间启动的每个 SDK,都必须说明为何需要在首帧或首次交互前运行。
将 SDK 分类为:启动关键型、首次交互必需型、可在首帧后运行型、特定功能按需延迟加载型,或仅后台运行型。
谨慎对待一概延迟的做法。崩溃报告、安全、深度链接、归因、推送路由、远程配置和功能标志可能有正确性要求。
当相关时,阅读 references/third-party-sdks-at-launch.md。
测量
当测量结果存在噪声时,请明确说明:
- 设备型号和 OS 版本
- Debug 与 Release/Profile 配置
- 模拟器或实体设备
- 冷启动/热启动/预热启动/恢复的分类
- 首次安装、更新后启动或回访用户启动
- 网络和账户状态
- 应用数据大小
- 已认证或未认证状态下的启动
- 测试迭代次数和方差
当测量设置或结果解读与任务相关时,阅读 references/metrics-instruments-xctest-metrickit.md。
参考资料路由
仅在任务需要更多细节时使用参考文件。
- 当任务涉及冷启动/热启动/预热启动/恢复术语、首帧目标、首次安装/更新后启动的分类或测量设置时,阅读
references/launch-taxonomy-and-targets.md。 - 当任务涉及 dyld、pre-main、
+load、+initialize、构造函数、Objective-C 类别、运行时注册或静态初始化时,阅读references/pre-main-dyld-and-static-initializers.md。 - 当任务涉及动态框架、静态库、可合并库、模块化、启动时链接的权衡、二进制布局或 order-file 相关事项时,阅读
references/linking-strategy.md。 - 当任务涉及启动步骤、关键路径建模、显式依赖、安全并行、竞争/死锁风险、故障处理或最长链优化时,阅读
references/launch-orchestration-and-dependency-graph.md。 - 当任务涉及
UIApplicationDelegate、UISceneDelegate、依赖项设置、根 UI 创建、首帧就绪或主线程启动工作时,阅读references/appdelegate-scenedelegate-and-first-frame.md。 - 当任务涉及 SwiftUI
App、WindowGroup、根视图设置、可观察状态、.task、.onAppear、scenePhase、@UIApplicationDelegateAdaptor或环境初始化时,阅读references/swiftui-app-launch.md。 - 当任务涉及分析、崩溃报告、广告、归因、远程配置、推送、功能标志、安全 SDK 或供应商初始化策略时,阅读
references/third-party-sdks-at-launch.md。 - 当任务涉及 Instruments、Time Profiler、signpost、XCTest 启动指标、MetricKit、Xcode Organizer、CI 基线或生产监控时,阅读
references/metrics-instruments-xctest-metrickit.md。
默认情况下不要阅读所有参考资料。
输出格式
审查代码或诊断启动报告时,请返回以下部分。
启动分类
说明问题似乎涉及冷启动、热启动、预热启动、首次安装/更新后启动、恢复,还是未知。
如存在测量歧义,请予以说明。
疑似阶段
指出最可能的阶段:
- pre-main
- 静态初始化
- 应用代理
- 场景设置
- SwiftUI 根视图设置
- 启动编排
- 首帧渲染
- 启动后的早期响应性
- 测量/设置问题
关键路径
如有足够信息,请指出必需的启动链。
如果隐藏的顺序关系、隐式依赖或未知依赖妨碍安全优化,请予以说明。
发现
列出在代码、架构、指标或跟踪记录中发现的具体风险。
避免提出与证据无关的通用建议。
建议的更改
按优先级对建议分组:
- 高置信度的启动路径修复
- 依赖/编排修复
- 所需的测量或检测
- 可选的架构整理
验证
说明如何在本地和生产环境中验证更改。
请说明应有所改善的预期指标、跟踪区域或启动阶段。
非目标
请勿将此技能用于:
- 一般滚动性能
- 内存泄漏
- 与应用启动无关的渲染优化
- 启动之外的网络性能
- 与应用启动无关的广泛应用架构审查
- 通用 SwiftUI 审查,除非代码会影响启动、首帧或早期响应能力