【问题标题】:Swift playground execution speedSwift Playground 执行速度
【发布时间】:2014-09-27 09:23:24
【问题描述】:

有没有办法提高游乐场的执行速度? 我想迭代许多周期而不是等待 10 分钟。

例如:

import UIKit

var count = 0
for var i = 0; i < 1000000000; i++ {
    count++
}

此代码将执行的时间过长。但我想快速获得结果。

【问题讨论】:

  • 也许优化编译器会将代码缩减为:var count = 1000000000
  • @Zaph 试着把这段代码粘贴到操场上,你就会明白我的意思了。
  • 这个网站上疯狂的近距离投票真的成了一个问题。很好的问题,感谢您发布它。
  • 我建议你根本不应该在操场上做那样的事情。我觉得 Apple 打算将 Playground 用于测试小 sn-ps 和想法,而不是运行 任何东西十亿次。由于代码在您编辑它时全部重新执行,并且具有实时显示值等,我真的看不出任何人能够让它运行得足够快以做任何事情十亿次,甚至是相当琐碎的。正如其他人所观察到的那样,优化编译器只会杀死您的循环,而优化器的许多其他功能会使游乐场的“实时视图”变得不可能。
  • 我使用 Playgrounds 不是为了衡量性能,而是为了进行一些计算。这个问题是有效的。

标签: ios swift swift-playground


【解决方案1】:

最大的性能杀手之一是操场右侧的输出。现在我将向您展示如何最小化此输出。

请参阅最后的示例代码。


最佳性能

最高效的方法是将所有性能关键代码放在 Playground 的 Sources 文件夹内的 .swift 文件中。

注意:要使用Sources 文件夹中的函数、类、属性和方法,您必须将它们标记为public。如果你想继承一个类,它必须被标记为open


性能好但代码难看

以下方法(我认为这不是官方/有意的)可用于禁用游乐场输出,但也会导致丑陋的代码。但是,它对于暂时禁用输出很有用。

有两种主要方法(和两个技巧)可以实现最小输出量(如果您找到更好的方法,请告诉我们):

  1. Void(或Void?)表达式周围使用括号,例如赋值(通常会导致无输出,另请参见3。)。

    var x = 0       // output: 0
    (x = 1)         // NO output
    (x = 2 * x - 1) // NO output
    (x.negate())    // NO output
    

    注意:在 Swift 中,赋值返回 Void,如果是 optional chaining,则返回 Void?

    var x: (Int, Int)? = nil
    if (x?.0 = 0) != nil {
        // assignment was successful (x!=0 and now x=(0, x.1))
    } else {
        // assignment was not successful (x==nil)
    }
    
  2. 分别初始化和声明变量。

    var x: Int // NO output
    (x = 0)    // NO output
    
  3. 如果 1. 不起作用,请在 () 上方或下方添加额外的 no-op(无操作)行。

    这发生在单行闭包中(可能在其他一些上下文中),例如:(另请参见下面的代码)

    [1, 4, 5, 6].mmap{
        () // without this line the line below would yield to an output
        ($1 = $0 + 1)
    } as [Int]
    
  4. 您也可以使用所有表达式的元组,然后将其分配给一个变量,而不是用括号括起来:

    var a: Any // this may be a useful definition in this context
    var x: Int
    var y: Int
    (a = (x = 0,
          y = 1,
          x = y + 1,
          y = x*x))
    

    但是这可能会导致压痕灾难...

哪里不行(我没发现如何删除输出;这个列表可能不完整):

  1. returns 在函数和闭包中
  2. Optional 变量的声明例如:var x: Int?

Sequence 上的新 map 方法示例

用法:见上文第 3 点。

Sequence.map的签名是

func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]

由于我还没有找到删除returns 输出的方法,因此可以使用带有inout 参数的闭包(通过赋值获取“返回”值)。一个可能的签名可能是:

func mmap<U>(_ transform: (Element, inout U?) -> ()) -> [U]

所以我们可以在inout 参数中传递nil,因为它是所有可能的U 的一个很好的默认值,而不会对U 施加约束,这可能需要实例生成器(例如:init() { ... })。

不幸的是,Swfit 很难推断出U,因此您需要通过显式类型注释来帮助编译器。此外,var newElement: U?确实在侧边栏中返回 nil

现在我将使用Any 而不是U?

extension Sequence {
    // ATTENTION: this is not as performant as the normal `map`!
    func mmap<U>(transform: (Element, inout Any) -> ()) -> [U] {
        var result: [U]
        (result = [U]())
        for element in self {
            var newElement: Any
            (newElement = 0) // some placeholder element
            (transform(element, &newElement))
            // assume the inout element to be of type `U`
            (result.append(newElement as! U))
        }
        return result // the ONLY output in this method
    }
}

您的示例代码

使用 Swift 4

var count = 0
for i in 0..<1_000_000_000 {
    (count += 1)
    if count % 100_000 == 0 {
        // print only every 100_000th loop iteration
        print(count)
    }
}

没有括号:每秒大约 10.000 次循环迭代

带括号:每秒大约 10.000.000 次循环迭代!!!

【讨论】:

    【解决方案2】:

    我感受到了你的痛苦,我正在将 2D 函数打印到 [Double] 然后转换为 UIImageView。其中一个步骤是迭代数百万像素,这需要很长时间。

    任何计算密集型、重复性或潜在耗时的内容都应放在 Playground 的“Sources”文件夹中。这样代码在你的 Playground 运行之前就被预编译了。将 for 循环的输出放在一个公共函数中,您可以从操场调用该函数。这样您就不必一直坐在那里看着操场计数通过for 循环。

    【讨论】:

      【解决方案3】:

      我遇到了这样的问题,经过几天的试验,我已经解决了。我需要做的就是将我所有的代码移动到 Playground 的文件夹 Sources 中。因此,之后执行速度提高了。 希望对你有帮助。

      注意:不要忘记使用公开课。

      【讨论】:

        【解决方案4】:

        为了加快 Xcode Playground 中的构建速度并防止加载图标永远旋转:

        1. 转到右侧边栏,在 Playground Settings 中将 iOS 更改为 macOS
        2. 不是导入 UIKit,而是导入 Foundation (如果您不尝试使用 UIKit 框架中的特定内容,这将起作用)

        【讨论】:

          猜你喜欢
          • 2015-03-29
          • 1970-01-01
          • 2011-02-17
          • 1970-01-01
          • 2021-02-18
          • 2016-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多