我有一个非常奇怪的问题,似乎是用最新的 Xcode 10.2 编译引起的。
我注意到我的应用程序启动时间明显变差(慢了 3 倍) ,这仅仅是因为使用 Xcode 10.2(.x) 构建并在 iOS 12.2 上运行。相同的代码修订版在旧版 iOS (12.0) 上运行或使用 Xcode 10.1 for iOS 12.2 编译时运行良好。
延迟甚至在main()
被调用之前就发生了。基本上控制台说Bootstrapping com.myapp.something with intent foreground-interactive
和main()
被调用之间的延迟是测量时间开始增加发生的地方。
应用程序设置(快速):
- 混合目标 Swift + Obj-C
- 使用内部框架进行代码分离
- 将 CocoaPods (1.5.3) 与框架一起使用
- 在运行时加载约 35 个内部框架(内部 + 主要是 CocoaPods)
这是发生的事情
旧代码修订版(Swift 4.2) - 以前运行良好的旧版本之一,然后使用 Xcode 10.1 编译
下表显示了使用 Xcode 10.2 编译对应用程序启动时间(状态栏淡入的第一帧开始的那一刻)的影响。
| | iOS 12.0 | iOS 12.2 |
|------------|----------|----------|
| Xcode 10.1 | 1x | 1.25x |
| Xcode 10.2 | 1x | 3x | <--
最后一个OK版本(iOS 12.0 / Xcode 10.1)的启动时间被认为是1x,其余的都是相对的。我们在这里说的是秒数(减去 3s -> 几乎是 9s)。
这种明显的延迟仅发生在全新安装时。随后的每次发射都再次快速。
最新代码 (Swift 5) - 所有代码迁移到 Swift 5,所有 CocoaPods 更新到最新的 Swift 5 兼容版本,项目更新到 Xcode 10.2 设置
与 Swift 5 之前的情况非常相似。所以 Swift 5 本身似乎不是问题。
编辑1:
Time Profiler 发现初始化时间变得非常慢。
结果_dyld_start
(动态框架的加载)速度慢了约 35 倍。
| | _dyld_start time |
|------------|------------------|
| Xcode 10.1 | 0.2s |
| Xcode 10.2 | 7.0s |
这意味着与 Xcode 10.2 + iOS 12.2 相关的某些内容会导致动态框架的加载变得非常缓慢。
将我的大约 35 个动态框架加载到运行时(大部分是 CocoaPods),性能下降似乎很大。不知道为什么会发生变化...
由于该问题仅发生在 iOS 12.2 + Xcode 10.2(支持 Swift 5)上,我想知道这个问题是否与 ABI 稳定性或其他问题有关。对我来说没有意义的是,当使用 Xcode 10.2 编译时,即使是在 Swift 5 迁移之前的代码也会发生这种情况。
到目前为止我已经尝试过:
- 更新到最新的 CocoaPods 1.7.0.rc.2 - 没有影响
- 使用 Time Profiler 进行测量
编辑2:
似乎是由动态链接器引起的。我们进行了一些调查,链接似乎在加载框架时在 iOS 12.2 上使用了不同的实现。
自 iOS 12.2 以来,在加载 (in ) 时在 Instruments 中提到了很多“递归”,ImageLoader::
并且似乎那里的递归出错了。堆栈跟踪似乎非常错误(请参见下面的屏幕截图)。
我想这里唯一的解决方法是删除框架并直接编译或使用静态库。
任何有关如何继续使用框架的帮助/想法表示赞赏!谢谢!
编辑3:
在第一个 iOS 13 Public beta 上,这个问题似乎不再发生了。
测量(下面的设置)告诉我,在 iOS 12.3.1 上启动相同的代码修订版所需的时间大约是 iOS 13 上的 3 倍。
在我看来,这确实是 iOS 12.x 上的错误。鉴于 iOS 13 很快就发布了,我认为 iOS 12.x 不会再出现任何修复(让 iPhone 6 等掉线的设备遭受损失......)。
测试设置:
- 运行相同的代码(Swift 5、Xcode 11 beta 2)
- 在相同的 iPhone 型号上运行 (iPhone 6S 16GB)
- 设备重启后冷应用启动
- 装有 iOS 12.3.1(最新稳定版)和 iOS 13(第一个公开测试版)的设备