Swift 字符串插值生成的字符串需要很长时间才能插入到字典中

Swift string interpolation produces string that takes very long to insert in a dictionary

在某些情况下,字符串插值生成的字符串用作字典键的速度比使用 String(format:) 生成的字符串慢得多。取以下代码:

var map = [String: String]()
let start = Date()
for _ in 0..<100000 {
    var s = "asdf"
    s = (s as NSString).appendingPathComponent("")
    s = transform(s)
    s = (s as NSString).substring(from: 1)
    map[s] = s
}
print(-start.timeIntervalSinceNow)

func transform(_ s: String) -> String {
    return "\(s)/\(s)"
//    return String(format: "%@/%@", s, s)
}

在我的 Mac 上,我在控制台中打印出时间间隔 0.69 秒(使用字符串插值时),但是在注释掉第 13 行和取消注释第 14 行时(以便我们使用 String(format:)) 我得到 0.33 秒的时间间隔,不到一半的时间。奇怪的是,只要取消注释第 5 行或第 7 行,字符串插值就会更快。另外,当注释掉第 8 行(map[s] = s)时,带有字符串插值的版本比带有 String(format:).

的版本快

这花了我很多时间才弄清楚,因为我希望这两种方法都能生成相同类型的字符串,但字符串插值总是更快。有人知道为什么吗?

不是字符串插值 vs 格式字符串本身需要时间,它与字典插入基本无关。

重要的是其余代码需要的 String 和 NSString 之间的上下文切换量

要看到这一点,请注释掉包含 (s as NSString) 的两行。现在您会发现格式字符串版本比字符串插值花费的时间要长得多。那是因为格式字符串引入了上下文切换。

使用您的原始代码,在两个 NSString 操作中间插入一个 String 操作意味着有 对上下文切换。这就是缓慢的根源。换句话说,如果您要完全切换到 NSString,请执行 all NSString stuff 直到完成,因此只有一个方向的上下文切换和一个上下文切换回到另一个方向。