快速的游乐场执行速度

Art*_*kov 13 ios swift swift-playground

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

例如:

import UIKit

var count = 0
for var i = 0; i < 1000000000; i++ {
    count++
}
Run Code Online (Sandbox Code Playgroud)

这段代码执行的时间太长了.但我希望得到快速的结果.

Qby*_*yte 8

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

请参阅最后的示例代码。


最棒的表演

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

注意:为了使用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
    
    Run Code Online (Sandbox Code Playgroud)

    注意:在 Swift 中,一个赋值返回Void,在可选链的情况下它是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)
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 分别初始化和声明变量。

    var x: Int // NO output
    (x = 0)    // NO output
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果 1. 不起作用,请在 上方或下方添加额外的无操作(无操作)行()

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

    [1, 4, 5, 6].mmap{
        () // without this line the line below would yield to an output
        ($1 = $0 + 1)
    } as [Int]
    
    Run Code Online (Sandbox Code Playgroud)
  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))
    
    Run Code Online (Sandbox Code Playgroud)

    然而,这可能会导致压痕灾难......

它不起作用的地方(我找不到如何删除输出的方法;此列表可能不完整):

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

一个新map方法的例子Sequence

用法:见上文第 3 点。

的签名Sequence.map

func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
Run Code Online (Sandbox Code Playgroud)

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

func mmap<U>(_ transform: (Element, inout U?) -> ()) -> [U]
Run Code Online (Sandbox Code Playgroud)

所以我们可以通过nilinout争论,因为它是一个很好的默认为每个可能的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
    }
}
Run Code Online (Sandbox Code Playgroud)

您的示例代码

使用 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


dsg*_*rnt 5

我感觉到你的痛苦,我正在玩打印 2D 函数[Double]然后转换为UIImageView. 其中一个步骤是迭代数百万个像素,并且花费了很长时间。

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