什么是 Swift String 到 NSString 的桥接开销?

Sem*_*nko 5 string performance bridge swift

我已经开始学习 Swift。我读到,当使用 Cocoa 类时,Swift String 被桥接到 NSString。这个操作的开销是多少?

Kev*_*vin 6

来自iOS 开发者库

Swift 自动在 String 类型和 NSString 类之间建立桥梁。

来自 Swift 源 -> stdlib/public/core/String.swift

String与 Objective-C 桥接为NSStringString 源自 Objective-C 的 a 可以将其字符存储在 NSString. 由于 的任意子类都NSString可以成为String,因此在这种情况下无法保证表示或效率。由于NSString是不可变的,所以就好像存储被某些副本共享:第一个是任何变异操作序列都会导致元素被复制到唯一的连续存储中,这可能会花费O(N)时间和空间,其中N是字符串表示形式的长度(或更多,如果底层证券NSString具有不寻常的性能特征)。

这些是我从该段落中得出的结论。注意:NSString是不可变的,我不确定 NSMutableString 如何工作,这可能与您的具体情况相关。

  1. 桥接NSStringtoString本质上是一个自由操作;无需转换。复杂度(1)
    • NSString使用 UTF-16 作为后备存储。String使用 UTF-16 或 ASCII,因此两个实例可以使用相同的内存。
  2. 但是,如果您随后更改该String结构,则需要从原始NSString. 在)
    • String如果不修改 的内存,则无法修改其后备内存NSString。这就是为什么内存必须被复制才能String拥有自己的内存。

swift 使用的支持StringCore 的源代码。

  • String 结构本身被复制了。目前它的大小为 3 个字,因此并不是一个昂贵的副本:1 个字用于开头,1 个字用于长度,1 个字用于缓冲区所有者。我认为(但已经验证)memcpy 指令之上的唯一开销是处理缓冲区所有者的任何引用计数。 (2认同)
  • 16 个字节的 memcpy(相对于我们这里的 12 个字节,尽管它们的速度可能相同)需要 0.7 纳秒,而 Objectvie-C 保留/释放将需要 23.3 纳秒。您的里程可能会有所不同,但 tldr 是“快得令人难以置信”。资料来源:https://www.mikeash.com/pyblog/friday-qa-2016-04-15-performance-comparisons-of-common-operations-2016-edition.html (2认同)