【问题标题】:iOS App is >20x slower after building with Xcode 11使用 Xcode 11 构建 iOS 应用程序后,速度要慢 20 倍以上
【发布时间】: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 包装器.详情请看我的回答。

标签: ios swift xcode performance 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 程序集编写代码以获得不错的性能......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 2017-02-13
    • 2021-01-04
    • 1970-01-01
    相关资源
    最近更新 更多