我有一个ObservableObject
可以完成 CPU 密集型繁重工作的程序:
import Foundation
import SwiftUI
@MainActor
final class Controller: ObservableObject {
@Published private(set) var isComputing: Bool = false
func compute() {
if isComputing { return }
Task {
heavyWork()
}
}
func heavyWork() {
isComputing = true
sleep(5)
isComputing = false
}
}
Run Code Online (Sandbox Code Playgroud)
我使用 aTask
在后台使用新的并发功能进行计算。这需要使用该@MainActor
属性来确保所有 UI 更新(此处与该属性相关isComputing
)都在主要参与者上执行。
然后,我有以下视图,其中显示一个计数器和一个启动计算的按钮:
struct ContentView: View {
@StateObject private var controller: Controller
@State private var counter: Int = 0
init() {
_controller = StateObject(wrappedValue: Controller()) …
Run Code Online (Sandbox Code Playgroud) 我阅读了有关 Swift 中枚举大小的文档,这是我的理解:
这个简单的仅包含一个“标签”来区分情况,默认情况下是一个UInt8
值,即small = 0
,medium = 1
等等。所以Size
的大小为 1 个字节,可以用 来验证MemoryLayout<Size>.size
。我还注意到,如果枚举的情况超过 255 个,显然标记大小会升级为 2 个字节。
enum Size {
case small
case medium
case large
}
Run Code Online (Sandbox Code Playgroud)
第二种情况,如果枚举具有关联值,则其行为类似于联合。在这种情况下,枚举大小是标记的大小加上最大关联值的大小。在以下示例中,大小为 1 字节 + 16 字节(字符串),即 17 字节,也可以使用 进行验证MemoryLayout
。
enum Size {
case small
case medium
case large
}
Run Code Online (Sandbox Code Playgroud)
最后一种情况,由于 Swift 是一种安全语言,使用标准非不安全 Swift 代码的引用始终有效,即始终指向内存中的值。T
这允许编译器在是引用类型时优化此类枚举:
enum Opt<T> {
case none
case some(T)
}
Run Code Online (Sandbox Code Playgroud)
这里类型的实例T
不能为nil
(NULL),因此编译器在这种none
情况下使用这个特殊值,因此当它是引用类型Opt
时,其大小为 …
在我的程序中,我严重依赖以下我认为非常常见的模式。有一个保存数据的结构(可以说Double
):
struct Container {
var data: Double
}
Run Code Online (Sandbox Code Playgroud)
接下来,创建该结构的数组,可能很大:
let containers = (0...<10_000_000).map { _ in
Container(data: .random(in: -10...10))
}
Run Code Online (Sandbox Code Playgroud)
然后,对数组应用 (map)reduce 操作以提取值,例如:
let sum = containers.reduce(0.0) { $0 + $1.data }
Run Code Online (Sandbox Code Playgroud)
我最初认为这个特定的操作会很快,因为该操作足够简单,编译器可以优化边界检查和其他慢速操作:没有奇怪的索引计算,闭包中没有捕获,一切都是不可变的,等等......
但是,我将性能与这种不安全的 reduce 数组实现进行了比较:
extension Array {
func unsafeReduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Element) throws -> Result
) rethrows -> Result {
try self.withUnsafeBufferPointer { buffer -> Result in
try buffer.reduce(initialResult, nextPartialResult)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我用完全优化编译了两个程序,-O -unchecked
我还使用了 Xcode 分析器来对程序进行计时,看来不安全的减少比安全的减少快 16 倍: …
我读了着名的为什么处理排序数组比未排序数组更快?我决定玩游戏并尝试其他语言,如Swift.我对2个非常相似的代码片段之间的运行时间差异感到惊讶.
在Swift中,可以在for-in循环中以直接方式或使用下标访问数组中的元素.例如这段代码:
for i in 0..<size {
sum += data[i]
}
Run Code Online (Sandbox Code Playgroud)
可写:
for element in data {
sum += element
}
Run Code Online (Sandbox Code Playgroud)
与size
所述data
长度和data
可累加元件的阵列.
所以,我只是在Swift(代码吼叫)中实现了与我在第一段中提到的问题相同的算法,令我惊讶的是第一种方法比第二种方法快大约5倍.
我真的不知道后台下标的实现,但我认为直接访问Swift for-in循环中的元素只是语法糖.
我的问题是两种for-in
语法之间有什么区别以及为什么使用下标更快?
这里是计时器的细节.我在2015年初的MacBook Air上使用Xcode 9.4.1和Swift 4.1以及Commande Line项目.
// Using Direct Element Access
Elapsed Time: 8.506288427
Sum: 1051901000
Run Code Online (Sandbox Code Playgroud)
VS
// Using Subscript
Elapsed Time: 1.483967902
Sum: 1070388000
Run Code Online (Sandbox Code Playgroud)
奖金问题:为什么Swift中的执行速度比C++慢100倍(两者都在Xcode项目的同一台Mac上执行)?例如,C++中的100,000次重复几乎与Swift中的1,000次重复相同.我的第一个猜测是,Swift是一种比C++更高级的语言,而Swift运行更多的安全检查.
这是我使用的Swift代码,我只修改了第二个嵌套循环:
import Foundation
import GameplayKit
let size = 32_768
var data = [Int]()
var sum = 0 …
Run Code Online (Sandbox Code Playgroud) 我正在使用 SwiftScanner
来解析文本文件中的字符串和数值。
由于卡特琳娜(10.15),可以使用scanDouble()
,scanInt()
,scanUpToCharacters(from:)
和scanUpTo(string:)
方法。它们都返回 Optionals。
在 Catalina 之前,这些函数直接通过引用工作并返回指示操作是否成功的布尔值。函数签名就像:scanDouble(&result)
. 当时我自己实现了上面四个功能是这样的:
fileprivate extension Scanner {
func scanUpToCharacters(from set: CharacterSet) -> String? {
var result: NSString?
return scanUpToCharacters(from: set, into: &result) ? (result as String?) : nil
}
func scanUpTo(_ string: String) -> String? {
var result: NSString?
return self.scanUpTo(string, into: &result) ? (result as String?) : nil
}
func scanDouble() -> Double? {
var double = 0.0
return scanDouble(&double) ? double …
Run Code Online (Sandbox Code Playgroud) 我是 python 的初学者,我在使用这段代码时遇到了问题:
count = 0
while count <15:
if count == 5:
continue
print(count)
count += 1
Run Code Online (Sandbox Code Playgroud)
当 count 的值 = 5 时,它会停止循环,就像有一个break语句一样。为什么会这样呢?请帮忙!
swift ×5
optimization ×2
break ×1
continue ×1
enums ×1
performance ×1
python ×1
reduce ×1
size ×1
swiftui ×1
while-loop ×1
xcode ×1