使用 Xcode 11 构建 iOS 应用程序后,速度要慢 20 倍以上

Posted

技术标签:

【中文标题】使用 Xcode 11 构建 iOS 应用程序后,速度要慢 20 倍以上【英文标题】:iOS App is >20x slower after building with Xcode 11 【发布时间】:2019-12-16 23:31:40 【问题描述】:

我有一个为 ios 12(使用 Xcode 10、Swift 4.2)开发的应用程序(Xcode 项目),现在我想使用 Xcode 11 为 iOS 13 重新构建它。

当我在 Xcode 11 中打开项目,构建并运行项目时,我发现我的应用程序突然慢了 20 多倍!我多次检查是否选择了发布配置,并且使用了与 Xcode 10 中相同的编译标志。不用说,编译器优化已被最大化,就像在 Xcode 10 中一样。

该应用程序使用大量 SIMD 操作(float4float3float4x4 等)并使用指针(例如 UnsafeMutablePointer<float4>)。我发现 Xcode 11 向我展示了像 float4 这样的 simd 类型现在已被弃用,typealiased 改为新的 SIMD 结构。

关于从 iOS 12 移植到 iOS 13,我应该知道一些明显的事情吗? SIMD 类型的这种变化会导致性能如此严重下降吗?如何恢复原来的速度(iOS 13 好像降级了)?

【问题讨论】:

你能用一个显示性能回归的热循环生成一个简单的minimal reproducible example 吗?然后包括为旧/新版本生成的 asm,以便具有 asm 经验的人可以告诉您这是否是原因。更改 SIMD 类型的定义方式很容易与将它们编译为更糟糕的 asm 相关联。 @PeterCordes 遗憾的是,我没有时间从我的代码库中提取 M(n)WE,但根据我的解决方案,很明显,阻碍性能的确实是 Swift 5 的新 SIMD 包装器.详情请看我的回答。 【参考方案1】:

我的钱花在 Xcode 11 上。Apple 可能更改了编译器或编译器设置,从而影响了矩阵数学指令的生成。

Apple 的 Xcode 主要版本有时肯定会破坏某些东西,他们可能需要一段时间才能解决问题。

在使用 Xcode 11 的同时尝试为 iOS 12 构建。然后采用相同的项目并从 Xcode 10.2 构建它。

我公司的应用程序非常庞大,在 Xcode 11 下构建时间增加了约 3 倍。这非常痛苦。显然,这是与执行速度不同的问题,但它仍然告诉您我们对构建过程进行了重大更改。

【讨论】:

我尝试为 iOS 12 和 13 构建,但遗憾的是,我看不出有任何区别。有没有其他使用 Neon SIMD 指令的方法? 哦,我觉得我不太理解——你建议让 Xcode 11 生成项目(通过针对 iOS 12)然后使用 Xcode 10 的编译器进行正确、快速的构建吗? 是的,看看是 Xcode 11 还是 iOS 13。切换回以 iOS 12 为目标,看看它是否慢。如果是这样,请使用 Xcode 10 清理并构建同一个项目。如果针对 iOS 12 的同一个项目在使用 Xcode 10 构建时运行速度很快,而在使用 Xcode 11 构建时运行缓慢,这意味着 Xcode 11。我会然后创建一个最小示例项目(如 float4x4 矩阵数学基准)并向 Apple 提交错误报告。 我尝试使用 Xcode 10.2.1 构建应用程序(我需要添加 iOS 13.3 Device Support),但应用程序仍然很慢。然后我尝试了 Xcode 10.1(还添加了对 iOS 13.3 的设备支持),该应用程序与原始应用程序一样快!编辑:在这两种情况下,我都针对 iOS 12,所以问题似乎是在 Xcode 10.2.1 和更高版本中引入的。 有趣的是,当我在 Xcode 10.2.1 中“跳转到定义…”float4 时,我看到了 SIMD4<Float> 类型别名的废话。当我在 Xcode 10.1 中做同样的事情时,我可以看到古老的 public struct float4 声明。基于这一观察,我认为减速确实是由于无用的SIMD4<Float> 重新设计。为什么他们必须改变工作系统……?有没有办法在较新的 Xcode 中强制使用 SIMD 类型的旧定义?【参考方案2】:

在我将大量 SIMD 的 Swift 代码库重写为 Objective-C 后,旧的性能得到了恢复。幸运的是,Objective-C 仍然使用良好的老式 SIMD 数据类型,没有毫无意义的包装器。

性能与 Swift 的 SIMD 实现的变化相关。在 Xcode 10.1 和更早版本中,Swift 使用内置的 SIMD 数据类型。在 Xcode 10.2(和更新版本)中,Apple 为 SIMD 数据类型(例如,float3SIMD4<Float> 的类型别名)和操作添加了无用的Object-Oriented wrapper,甚至懒得测试性能,这使得我的代码超过了 慢 20 倍。

有时你只需要速度,不要在不属于它的地方强加面向协议的设计。

无论您选择在 Xcode 10.2 及更高版本中使用 Swift 4 还是以 iOS 12 为目标,您仍然会获得同样糟糕的 SIMD 性能。

TL;DR: Apple 将 Swift-5 之前的 SIMD 性能水平搞砸了 in Xcode 10.2 和更高版本。将您的 SIMD 繁重的代码移植到 Objective-C 以获得良好的旧级别性能(在我的情况下快 20 倍)。让我们希望 Apple 不会接触 Objective-C,否则我们很快就会用 Neon 程序集编写代码以获得不错的性能......

【讨论】:

以上是关于使用 Xcode 11 构建 iOS 应用程序后,速度要慢 20 倍以上的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 版本 9.1 (9B55) 上传存档失败 - iOS 11.1 - 应用程序必须使用公共 (GM) 版本构建

使用 XCode 8 修复 iOS 11 崩溃

Crashlytics 线程仅在使用 Xcode 11 构建的 iOS 13 上崩溃

Xcode 11 GM-设备启动后应用程序崩溃由于信号9而终止

有没有办法使用 Xcode 12.x 构建 iOS 15 应用程序?

为 iOS 编译 Flutter 项目时的 Xcode 构建问题