What is the runtime cost of Swift's casts?
casting, overhead, swift, time-complexity
Solution
It is O(1) (almost 0) if it is obviously castable(like numeric casting and upcasting): case 1, 2, 3.
For other non-collection castings, it is obviously O(1): case 4, 5.
For collection downcastings:
- `as?` is O(n) because element type checking is performed eagerly.
- Native forced downcasting is O(1) because element type checking is deferred: case 6.
- Bridged forced downcasting(`NSArray as! [NSDate]`) is O(n) because element type checking is performed eagerly.
- Nested collections are recursively casted so you just apply the above rules recursively.
Sources:
- https://github.com/apple/swift/blob/master/stdlib/public/runtime/Casting.cpp
- https://github.com/apple/swift/blob/master/stdlib/public/core/ArrayCast.swift
- https://github.com/apple/swift/blob/master/stdlib/public/core/HashedCollections.swift.gyb
Problem
What are the different runtime costs incurred by the following type casts? Numeric cast of constant, e.g.: ``` let f = 0.1 as CGFloat ``` I'd imagine this has zero runtime cost. Numeric cast of runtime value, e.g.: ``` let f = someDoubleValue as CGFloat ``` I'd imagine this has an extremely small runtime cost. Upcast, e.g.: ``` let dict: [String: Int] = ... let anyObj = dict as AnyObject ``` I'd expect this to have zero runtime cost. Failable Downcast, e.g.: ``` let anyObj: AnyObject = ... if let str = anyObj as? String { ... } ``` I'd expect this to have a runtime cost proportional to the number of classes in the hierarchy of the dynamic type of `anyObj`. Forced Downcast, e.g.: ``` let anyObj: AnyObject = ... let str = anyObj as! String ``` Maybe the cost for a forced downcast is slightly lower? Forced Downcast of collection, e.g.: ``` let dates: [AnyObject] = ... for date in dates as! [NSDate] { ... } ``` What happens here — especially when `dates` comes from an `NSArray`? Is the runtime cost of this cast proportional to the number of its elements? What if I cast to a more complex collection type like `[String: [String: [Int]]]` — is the whole collection traversed to make sure all its elements and subelements conform to this cast? For each of the first four cases, are my assertions true?