gpt4 book ai didi

ios - Swift 字符串插值性能

转载 作者:可可西里 更新时间:2023-11-01 00:56:15 35 4
gpt4 key购买 nike

我的 iOS/Swift 项目中有很多 print() 语句。我编写了如下全局覆盖,以便在发布版本中忽略这些:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
#if DEBUG
Swift.print(items, separator: separator, terminator: terminator)
#endif
}

当调用 print() 时,我有时会传入具有昂贵的自定义 debugDescription 属性的对象,例如:

print("Value of myArray: \(myArray)")

使用 myArray 实现自定义 debugDescription,如下所示:

var debugDescription: String {
get {
// Serialise the array for printing
}
}

我的问题是,debugDescription 值是在将字符串传递给 print() 之前还是之后计算的? IE。 #if DEBUG 预处理器指令是否会消除发布版本的计算?

编辑:我知道 debugDescription 是一个计算属性,我只是不确定它何时被调用。我不是自己调用它;它作为字符串插值的一部分自动调用。因此,如果 Swift 在将字符串传递给 print() 之前对其进行插值,它仍然会计算该属性。但是如果 Swift 保存“指令”而不是只计算内部内置 Swift.print() 函数中的字符串,那么我会获得性能提升。因此,这个问题实际上是关于 Swift 如何在性能方面处理字符串插值。

最佳答案

will the #if DEBUG preprocessor directive eliminate the computation from release builds?

不,不会。 Swift 在函数被调用时评估所有函数参数。您可以在调试器中或通过将对 Swift.print 的调用添加到您的 debugDescription 实现来验证这一点。例如,创建一个包含以下内容的文件:

// test.swift
struct A: CustomDebugStringConvertible {
let value: Int

var debugDescription: String {
Swift.print("Calling debugDescription")
return "A: \(value)"
}
}

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
#if DEBUG
Swift.print(items, separator: separator, terminator: terminator)
#endif
}

let a = A(value: 42)
print("Value of a: \(a)")

然后,在终端中:

> swift test.swift
Calling debugDescription

如您所见,"Calling debugDescription" 得到打印(即,debugDescription 得到评估),即使您的 print 函数没有做任何事情。现在让我们设置 DEBUG 标志:

> swift -D DEBUG test.swift
Calling debugDescription
["Value of a: A: 42"]

这就是为什么Swift标准库中类似的函数(比如assert)使用autoclosures的原因他们的一个或多个参数。 @autoclosure 属性将函数参数包装在闭包中。这样,被调用的函数可以决定是否以及何时评估表达式(通过调用函数)。这对调用者是完全透明的。

不幸的是,@autoclosure 不适用于可变参数(如 Any...),所以我认为没有办法完全重现您想要的内容在 swift 4.0 中。但是,如果您可以接受采用单个 Any 参数的 print 函数,则可以像这样定义您的函数:

func print(_ item: @autoclosure () -> Any, separator: String = " ", terminator: String = "\n") {
#if DEBUG
Swift.print(item(), separator: separator, terminator: terminator)
#endif
}

现在,在您调用 item() 之前,该函数不会评估其第一个参数,这只发生在 #if DEBUG block 内,因此在 release 中没有开销构建。

关于ios - Swift 字符串插值性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47542966/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com