有没有办法提高Playground的执行速度?我想迭代多个周期而不必等待10分钟。
例如:
import UIKit
var count = 0
for var i = 0; i < 1000000000; i++ {
count++
}
这段代码执行时间太长了,但我希望能够快速得到结果。
有没有办法提高Playground的执行速度?我想迭代多个周期而不必等待10分钟。
例如:
import UIKit
var count = 0
for var i = 0; i < 1000000000; i++ {
count++
}
这段代码执行时间太长了,但我希望能够快速得到结果。
最大的性能杀手之一是游乐场右侧的输出。现在我将向您展示如何最小化此输出。
请查看示例代码结尾。
最有效的方法是将所有关键性能代码放在播放器中Sources
文件夹内的.swift
文件中。
注意:为了使用来自Sources
文件夹的函数、类、属性和方法,必须将它们标记为public
。如果想要子类化一个类,则必须将其标记为open
。
以下方法(我认为这不是官方/预期的)可用于禁用游乐场输出,但也会导致丑陋的代码。然而,它适用于临时禁用输出。
有两种主要方法(和两个技巧)可以实现最小量的输出(如果您找到更好的方法,请告诉我们):
Use parenthesis around Void
(or Void?
) expressions like assignments (normally leads to no output, see also 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?
.
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)
}
Initialize and declare variables separately.
var x: Int // NO output
(x = 0) // NO output
If 1. does not work add an additional no-op (no operation) line above or below ()
.
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]
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...
无效的情况(我找不到删除输出的方法;此列表可能不完整):
return
var x: Int?
Sequence
上新的 map
方法示例用法:请参考上面的第3点。
Sequence.map
的签名为:
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
由于我还没有找到删除return
输出的方法,因此可以使用带有inout
参数的闭包(通过赋值获取“返回”值)。可能的签名如下:
func mmap<U>(_ transform: (Element, inout U?) -> ()) -> [U]
所以我们可以在 inout
参数中传递 nil
,因为它是每个可能的 U
的良好默认值,而不会对 U
施加任何约束,这可能需要一个实例生成器(例如:init() { ... }
)。
不幸的是,Swift 很难推断出 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个循环迭代!!!
我理解你的痛苦,我曾经尝试将2D函数打印到[Double]
,然后转换为UIImageView
。其中一个步骤是迭代数百万个像素,这需要很长时间。
任何计算密集、重复或潜在耗时的任务都应该放在playground的"Sources"文件夹中。这样,在运行playground之前代码就已经被预编译了。将那个for
循环的输出放在一个公共函数中,你可以从playground中调用它。这样你就不必坐在那里看着playground数遍历for
循环的次数了。
我曾经遇到过这样的问题,但是经过数天的尝试,我已经解决了它。我所需要做的就是将所有代码移动到playground的Sources
文件夹中。这样一来,执行速度就得到了提升。
希望这能对你有所帮助。
注意:不要忘记使用开放类。
var count = 1000000000
。 - zaph