【问题标题】:Swift Performance with instance property arrays具有实例属性数组的 Swift Performance
【发布时间】:2016-08-09 12:15:03
【问题描述】:

我遇到了一个有趣的 Swift 性能问题,正在寻找一些建议,分析为什么会发生这种情况。

我有一个算法,需要在循环中进行数十万次数组访问。我发现如果我将数组作为实例属性引用(从同一个类实例内部),性能很差。似乎该数组在每次迭代时都被取消引用。考虑到数组是 same 类的成员,这似乎很奇怪。 self.x 不会要求 x 一遍又一遍地取消引用吗?等效的 Java 代码没有同样的性能问题。

在下面的例子中,test3 需要 0.5 秒,test4 需要 0.15 秒。

每次我做某事时,我真的必须检查所有代码并分配本地范围的数组吗?

欢迎任何提示/想法。我将编译器优化设置为 Fast-O。

西蒙

编辑:这篇文章在这里详细说明了答案: https://developer.apple.com/swift/blog/?id=27

希望对您有所帮助。长话短说,类作用域变量的 private/final 将消除不必要的间接访问数组的需要。

class MyClass {

    var array_1 = [Int64] (count: 16 , repeatedValue: 0)
    var array_2 = [Int64] (count: 16 , repeatedValue: 0)


    func runTest3() {
        // test #3
        //
        let start = NSDate().timeIntervalSince1970
        for i in 0 ... 10000000 {
            if (array_1[ i%16 ] & array_2[ i%16 ] ) != 0  {
                // whatever
            }
        }
        let passed = NSDate().timeIntervalSince1970 - start
        print("3 time passed: \(passed)")
    }

    func runTest4() {
        // test #4
        //
        let start = NSDate().timeIntervalSince1970
        let localArray_1 = self.array_1
        let localArray_2 = self.array_2
        for i in 0 ... 10000000 {
            if (localArray_1[ i%16 ] & localArray_2[ i%16 ] ) != 0  {
                // whatever
            }
        }
        let passed = NSDate().timeIntervalSince1970 - start
        print("4 time passed: \(passed)")
    }
}

【问题讨论】:

  • 我用 -O 编译了这个,每个不到 0.01 秒。这可能取决于你在循环中做了什么。
  • 如果你这样做 ...let localarray = self.array.. Swift 不会复制数组,他只是“指向”内存并记录数组的更改(有点像 git正在工作)所以以这种方式使用它是节省的
  • 是的,localArray 方法已经足够安全了,它只是防止了 self.???每次迭代都会取消引用。
  • @jtbandes - 我在 Swift 编译器代码生成中设置了 -O,但我得到了这个:3 次过去了:0.44688892364502 4 次过去了:0.0145220756530762
  • 你有任何代码替换“whatever”吗?

标签: ios arrays swift performance


【解决方案1】:

https://developer.apple.com/swift/blog/?id=27

类范围变量的 Private/Final 消除了性能问题。原因见上篇文章。感谢大家的帮助。

【讨论】:

  • 看起来你的链接指向了同样的问题,而不是你想要的帖子。
  • @TimurKuchkarov - 哎呀,谢谢你接受这个。现在修复链接。周日深夜,大脑僵在那里。干杯
  • 这个答案可能会误导用户。只要打开了整个模块优化(应该是发布模式),出于性能原因,几乎不需要将方法标记为最终/私有。这些标记是为了向其他程序员表达你的意图。请参阅链接博客文章的最后一部分,了解 WMO 如何解决此问题。
猜你喜欢
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2014-12-28
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 2018-07-20
  • 1970-01-01
相关资源
最近更新 更多