跳到主要内容

启动优化

问题

iOS App 冷启动的完整过程?如何做启动优化?

答案

冷启动两阶段

pre-main 优化

优化项方法
减少动态库合并动态库(Apple 建议 < 6 个自定义动态库)
减少 ObjC 类删除无用类,合并小类
避免 +load改用 +initialize 或延迟初始化
二进制重排减少 Page Fault(Clang 插桩获取启动调用顺序)

main 之后优化

// ❌ didFinishLaunching 中初始化所有 SDK
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: ...) -> Bool {
initCrashSDK() // 必须立即
initNetworking() // 必须立即
initAnalytics() // 可延迟
initPushSDK() // 可延迟
initAdSDK() // 可延迟
return true
}

// ✅ 分级初始化
func application(...) -> Bool {
// 第一优先级:崩溃收集、网络
initCrashSDK()
initNetworking()

// 延迟到首屏渲染后
DispatchQueue.main.async {
self.initAnalytics()
self.initPushSDK()
}

// 延迟到用户空闲时
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.initAdSDK()
}
return true
}

度量

// Xcode: Edit Scheme → Run → Arguments → Environment Variables
// 添加 DYLD_PRINT_STATISTICS = 1
// 控制台输出 pre-main 耗时

// 代码测量 main 后耗时
let start = CFAbsoluteTimeGetCurrent()
// ... 首屏加载后
let elapsed = CFAbsoluteTimeGetCurrent() - start

常见面试问题

Q1: 二进制重排是什么原理?

答案:App 启动时会访问大量函数,如果这些函数分散在不同内存页,会产生多次 Page Fault(缺页中断,每次约 0.1-1ms)。二进制重排把启动时调用的函数排列到连续内存页中,减少 Page Fault 次数。通过 Clang 插桩(__sanitizer_cov_trace_pc_guard)记录启动函数调用顺序,生成 order 文件给链接器。

相关链接