简体   繁体   English

快速的游乐场执行速度

[英]Swift playground execution speed

Is there a way to increase execution speed of a playground? 有没有办法提高游乐场的执行速度? I want to iterate many cycles and not to wait 10 minutes. 我想迭代很多周期而不是等待10分钟。

For example: 例如:

import UIKit

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

This code will execute a way too long. 这段代码执行的时间太长了。 But I want to get quick result. 但我希望得到快速的结果。

I feel your pain, I was playing around with printing 2D functions to [Double] then converting to UIImageView . 我感觉到你的痛苦,我正在玩2D打印功能到[Double]然后转换为UIImageView One of the steps was iterating over millions of pixels, and it took forever. 其中一个步骤是迭代数百万个像素,这需要永远。

Anything computationally intensive, or repetitive, or potentially time consuming should be put in the "Sources" folder of the playground. 任何计算密集,重复或可能耗时的东西都应该放在操场的“Sources”文件夹中。 That way the code is precompiled before your playground is run. 这样代码就会在你的游乐场运行之前进行预编译。 Put the output of that for loop in a public function that you can call from the playground. for循环的输出放在可以从操场上调用的公共函数中。 Then you won't have to sit there watching the playground count all the times it went through the for loop. 然后你不必坐在那里看着游乐场计数它经历了for循环。

One of the biggest performance killer is the output at the right side of the playground. 最大的性能杀手之一是操场右侧的输出。 Now I will show you how to minimize this output. 现在我将向您展示如何最小化此输出。

See at the end for your example code. 请参阅最后的示例代码。


Best Performance 最棒的表演

The most performant way is to make all the performance critical code in a .swift file inside the Sources folder in the playground. .swift方法是在操场中的Sources文件夹中的.swift文件中创建所有性能关键代码。

Note: In order to use the functions, classes, properties and methods from the Sources folder you have to mark them public . 注意:要使用Sources文件夹中的函数,类,属性和方法,必须将它们标记为public If you want to subclass a class it has to be marked open . 如果要将类子类化,则必须将其标记为open


Good Performance but ugly code 良好的性能,但丑陋的代码

The following method (I think this is not official/intended) can be used to disable the playground output but also leads to ugly code. 以下方法(我认为这不是官方/意图)可用于禁用操场输出,但也会导致丑陋的代码。 However it is good for temporary disabling the output. 但是暂时禁用输出是有好处的。

There are two main ways (and two tricks) to achieve the minimum amount of output ( If you find a better way let us know ): 实现最小输出量有两种主要方式(和两种技巧)( 如果您找到更好的方式让我们知道 ):

  1. Use parenthesis around Void (or Void? ) expressions like assignments (normally leads to no output, see also 3.). Void (或Void? )表达式周围使用括号,如赋值(通常导致无输出,另请参见3.)。

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

    Note: In Swift an assignment returns Void and in case of optional chaining it is Void? 注意:在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) } 
  2. Initialize and declare variables separately. 分别初始化和声明变量。

     var x: Int // NO output (x = 0) // NO output 
  3. If 1. does not work add an additional no-op (no operation) line above or below () . 如果1.不起作用,则在上方或下方添加额外的无操作(无操作)行()

    This happens in single line closures (and probably in some other contexts) for example: (see also the code below) 这种情况发生在单行闭包中(可能在其他一些上下文中),例如:(另见下面的代码)

     [1, 4, 5, 6].mmap{ () // without this line the line below would yield to an output ($1 = $0 + 1) } as [Int] 
  4. Instead of wrapping every line in parenthesis you can also use a tuple of all the expressions which is then assigned to a variable: 您可以使用所有表达式的元组,然后将其分配给变量,而不是将每一行包装在括号中:

     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)) 

    However this could lead to a indentation disaster... 然而,这可能导致压痕灾难......

Where it does not work (I've found no way how to remove the output; This list is probably not complete): 哪里不起作用 (我找不到如何删除输出;这个列表可能不完整):

  1. return s in functions and closures 在函数和闭包中return s
  2. Declaration of Optional variables eg: var x: Int? 声明Optional变量例如: var x: Int?

An example of a new map method on Sequence Sequence上新的map方法示例

Usage: See above at Point 3. 用法:见上文第3点。

The signature of Sequence.map is Sequence.map的签名是

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

Since I have not found a way how to remove the output of return s one can use a closure with an inout argument (get the "return" value with an assignment). 由于我还没有找到如何删除return s输出的方法,因此可以使用带有inout参数的闭包(通过赋值获取“return”值)。 A possible signature could then be: 可能的签名可能是:

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

so we can pass nil in the inout argument since it is a good default for every possible U without imposing a constraint on U which could require an instance generator (eg: init() { ... } ). 所以我们可以把nilinout参数,因为它是为每个可能的一个很好的默认U没有强加约束U这可能需要一个实例生成器(例如: init() { ... }

Unfortunately Swfit has a hard time to infer U so you would need to help the compiler with explicit type annotations. 不幸的是,Swfit很难推断U因此您需要使用显式类型注释来帮助编译器。 In addition var newElement: U? 另外var newElement: U? does return nil in the sidebar. 不会返回nil在侧边栏。

Now I will use Any instead of U? 现在我将使用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
    }
}

Your example code 你的示例代码

Using Swift 4 使用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)
    }
}

Without the parenthesis: about 10.000 loop iterations per second 没有括号:每秒大约10.000次循环迭代

With parenthesis: about 10.000.000 loop iterations per second !!! 带括号:每秒大约10.000.000循环迭代!!!

I had a such problem and I have solved it after days of trials. 我遇到了这样的问题,经过几天的试验,我已经解决了这个问题。 All I needed to do is move all my code in folder Sources of playground. 我需要做的就是将所有代码移动到操场上的Sources文件夹中。 So, after that the execution speed was enhanced. 因此,之后执行速度得到提升。 I hope it helps you. 我希望它对你有所帮助。

Note: don't forget to use open classes. 注意:不要忘记使用开放类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM