Swift 的转换的运行时成本是多少?
What is the runtime cost of Swift's casts?
以下类型转换会产生哪些不同的运行时成本?
常数的数字转换,例如:
let f = 0.1 as CGFloat
我认为这具有零运行成本。
运行时值的数字转换,例如:
let f = someDoubleValue as CGFloat
我认为这具有极小的运行时成本。
Upcast, 例如:
let dict: [String: Int] = ...
let anyObj = dict as AnyObject
我希望它的运行时成本为零。
失败的向下转换,例如:
let anyObj: AnyObject = ...
if let str = anyObj as? String { ... }
我希望它的运行时成本与 anyObj
.
动态类型层次结构中 类 的数量成正比
强制向下转换,例如:
let anyObj: AnyObject = ...
let str = anyObj as! String
也许强制向下转换的成本稍微低一些?
强制向下转换集合,例如:
let dates: [AnyObject] = ...
for date in dates as! [NSDate] { ... }
这里发生了什么——尤其是当 dates
来自 NSArray
时?此转换的运行时成本与其元素数量成正比吗?如果我转换为更复杂的集合类型,如 [String: [String: [Int]]]
会怎么样——是否遍历整个集合以确保其所有元素和子元素都符合此转换?
对于前四种情况,我的断言都是正确的吗?
如果明显可转换(如数字转换和向上转换),则为 O(1)(几乎为 0):情况 1、2、3。
对于其他非集合的铸件,显然是O(1): case 4, 5.
对于集合向下转型:
as?
是 O(n),因为元素类型检查是急切执行的。
- 本机强制向下转换为 O(1),因为元素类型检查被推迟:情况 6。
- 桥接强制向下转换(
NSArray as! [NSDate]
)是 O(n),因为元素类型检查是急切执行的。
- 嵌套集合是递归转换的,因此您只需递归应用上述规则即可。
来源:
只是想补充一点,协议类型转换的运行时成本非常高。我试图在反汇编视图中查看它,只是忘记了正在发生的事情。所以像这样的一行:
(self as! SomeProtocol).someMethod()
导致 retain/release(涉及内存障碍),然后调用旧的 objc_msgSend()
(!) 但与 someMethod()
无关,我想是因为其中之一self
或 SomeProtocol
源自 class
,然后是一个非常非常长的函数调用链,其中包含一些循环。就像我说的那样,我失去了耐心尝试在反汇编视图中调试这一行代码。
虽然协议是一个非常好的抽象,但在性能关键代码中应该谨慎使用它们。
以下类型转换会产生哪些不同的运行时成本?
常数的数字转换,例如:
let f = 0.1 as CGFloat
我认为这具有零运行成本。
运行时值的数字转换,例如:
let f = someDoubleValue as CGFloat
我认为这具有极小的运行时成本。
Upcast, 例如:
let dict: [String: Int] = ... let anyObj = dict as AnyObject
我希望它的运行时成本为零。
失败的向下转换,例如:
let anyObj: AnyObject = ... if let str = anyObj as? String { ... }
我希望它的运行时成本与
anyObj
. 动态类型层次结构中 类 的数量成正比
强制向下转换,例如:
let anyObj: AnyObject = ... let str = anyObj as! String
也许强制向下转换的成本稍微低一些?
强制向下转换集合,例如:
let dates: [AnyObject] = ... for date in dates as! [NSDate] { ... }
这里发生了什么——尤其是当
dates
来自NSArray
时?此转换的运行时成本与其元素数量成正比吗?如果我转换为更复杂的集合类型,如[String: [String: [Int]]]
会怎么样——是否遍历整个集合以确保其所有元素和子元素都符合此转换?
对于前四种情况,我的断言都是正确的吗?
如果明显可转换(如数字转换和向上转换),则为 O(1)(几乎为 0):情况 1、2、3。
对于其他非集合的铸件,显然是O(1): case 4, 5.
对于集合向下转型:
as?
是 O(n),因为元素类型检查是急切执行的。- 本机强制向下转换为 O(1),因为元素类型检查被推迟:情况 6。
- 桥接强制向下转换(
NSArray as! [NSDate]
)是 O(n),因为元素类型检查是急切执行的。 - 嵌套集合是递归转换的,因此您只需递归应用上述规则即可。
来源:
只是想补充一点,协议类型转换的运行时成本非常高。我试图在反汇编视图中查看它,只是忘记了正在发生的事情。所以像这样的一行:
(self as! SomeProtocol).someMethod()
导致 retain/release(涉及内存障碍),然后调用旧的 objc_msgSend()
(!) 但与 someMethod()
无关,我想是因为其中之一self
或 SomeProtocol
源自 class
,然后是一个非常非常长的函数调用链,其中包含一些循环。就像我说的那样,我失去了耐心尝试在反汇编视图中调试这一行代码。
虽然协议是一个非常好的抽象,但在性能关键代码中应该谨慎使用它们。