swift 4 : Are Strings reference counted & how to get that count

标签 swift string performance optimization reference-counting

这个性能优化 WWDC 视频表明字符串是引用计数的,因为它们在堆上。这会影响带有字符串的结构的性能,以及 Swift 4 中是否发生了某些变化(现在字符串再次成为集合 - 写入时复制)。好奇如何证明这一点并获得实际计数。 CFGetRetainCount - 不适用于字符串。

参见 https://developer.apple.com/videos/play/wwdc2016/416/

enter image description here

使用 Swift 4。

最佳答案

Swift 字符串是没有引用计数的值类型。但是字符串包含的字符保存在一个引用类型容器存储的堆中,并且有引用计数。

这就是为什么 Swift Strings 具有写时复制优化 - 就像其他集合一样 -

在 Structs 内部使用字符串——以及任何其他引用类型——对于性能来说并不是一个好主意,因为在 Struct 本身的每次赋值中,所有其他引用类型和字符串存储都会被保留。

当你有一个包含 N 引用类型的值类型时,在每次赋值/取消初始化时你需要 N 保留/释放。并且您将有值类型的复制开销。

但是,如果您定义一个包含N 个引用类型的引用类型,则在每次赋值/取消初始化时,您将只有1 个保留/释放操作。

对于表达式:

struct Label {
    var text: String
    var font: UIFont
    func draw() { }
}

let label1 = Label(text: "Hi", font: font)
let label2 = label1
retain(label2.text._storage)
retain(label2.font)
// finished using label1
release(label1.text._storage)
release(label1.font)
// finished using label2
release(label2.text._storage)
release(label2.font)

如果 Label 是作为一个类来实现的,它将是

class Label {
        var text: String
        var font: UIFont
        func draw() { }
}

let label1 = Label(text: "Hi", font: font)
let label2 = label1
retain(label2)
// finished using label1
release(label1)
// finished using label2
release(label2)

另一方面,这种方法与结构的线程安全提议相冲突。相同的实例将在所有副本之间共享。

由于保留/释放操作在堆上并且它们必须是线程安全的,因此这些操作的成本相当高。

因此,如果您确实需要出色的性能(包括微优化),并且希望明智地使用值类型,则应该考虑这种方法。

PS:Swift 4并没有改变这种做法,写时复制是另一种优化。只有当包含具有多个引用的引用类型的值类型发生变化时,它才会创建一个副本。

关于 swift 4 : Are Strings reference counted & how to get that count,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46247494/

相关文章:

swift - Xcode 10 存档构建编译失败

matlab - 考虑每行的所有可能排列,查找元胞数组的唯一行

c# - 哪一个是清除字符串生成器的性能明智的?

swift - 在swift中的代码中修改其高度约束后,UILabel不显示全文

ios - Xcode 10.0 错误 "Command/Applications/Xcode 10.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1"

swift - 尽管导入了所有包,但无法在范围内找到 'logger'

java - 为什么下面程序的输出是1而不是2?

javascript - JavaScript 中带有 null 和 undefined 的字符串连接

java - 当我们不传递任何命令行参数时,为什么不会出现错误?

linux - Linux 中的高性能数据包处理