Swift的演员阵容的运行时成本是多少?

时间:2015-02-19 09:40:09

标签: swift casting time-complexity overhead

以下类型转换会产生哪些不同的运行时成本?

  1. 常量的数字广播,例如:

    let f = 0.1 as CGFloat
    

    我认为这没有运行时间成本。

  2. 运行时值的数字转换,例如:

    let f = someDoubleValue as CGFloat
    

    我想这会有非常小的运行时成本。

  3. Upcast ,例如:

    let dict: [String: Int] = ...
    let anyObj = dict as AnyObject
    

    我希望它的运行时成本为零。

  4. 可投降的,例如:

    let anyObj: AnyObject = ...
    if let str = anyObj as? String { ... }
    

    我希望它的运行时成本与动态类型anyObj的层次结构中的类数量成比例。

  5. 强制向下倾斜,例如:

    let anyObj: AnyObject = ...
    let str = anyObj as! String
    

    强迫低价的成本可能略低一些?

  6. 强制收集广告,例如:

    let dates: [AnyObject] = ...
    for date in dates as! [NSDate] { ... }
    

    这里会发生什么 - 特别是当dates来自NSArray时?此演员的运行时成本是否与其元素的数量成比例?如果我转换为更复杂的集合类型,如[String: [String: [Int]]],那么整个集合是否遍历以确保其所有元素和子元素都符合此类演员?

  7. 对于前四种情况中的每一种情况,我的断言都是真的吗?

2 个答案:

答案 0 :(得分:17)

  • 如果它是明显可铸造的(如数字铸造和向上铸造),则为O(1)(几乎为0):案例1,2,3。

  • 对于其他非收集铸件,显然是O(1):案例4,5。

  • 收集向下转发:

    • as?是O(n),因为要急切地执行元素类型检查。
    • 原生强制向下转换为O(1),因为元素类型检查是延迟的:案例6。
    • 桥接强制向下转换(NSArray as! [NSDate])是O(n),因为要热切地执行元素类型检查。
    • 嵌套集合以递归方式呈现,因此您只需递归应用上述规则。

来源:

  1. https://github.com/apple/swift/blob/master/stdlib/public/runtime/Casting.cpp
  2. https://github.com/apple/swift/blob/master/stdlib/public/core/ArrayCast.swift
  3. https://github.com/apple/swift/blob/master/stdlib/public/core/HashedCollections.swift.gyb

答案 1 :(得分:0)

只是想补充一下,协议类型转换的运行时成本是惊人的。我试图在反汇编视图中查看它,而只是不了解发生了什么。像这样的一行:

(self as! SomeProtocol).someMethod()

导致保留/释放(涉及内存障碍),然后调用了旧商品objc_msgSend()(!),但与someMethod()无关,我想是因为{{1} }或self是从SomeProtocol派生的,然后是非常长的函数调用链,其中涉及一些循环。就像我说的那样,我在尝试在反汇编视图中调试这一行代码时失去了耐心。

虽然协议是非常好的抽象,但应在性能关键代码中谨慎使用。