swift - 为什么 indexingIterator.next() 使用动态调度?
问题描述
为什么 for-in 比在快速调试模式下慢?
我写了这个。感谢那些回答我的人,我本可以学习Seqeunce
和IteratorProtocol
.
所以我实现School
了符合的自定义类型(下面的代码)Sequence
。我检查了 Xcode-time 配置文件。
但如果只使用range
and for-in
,时间分析器显示 协议见证。
为什么indexingIterator.next()
使用动态方法而不是 in School
?我认为即使struct
符合protocol
,如果变量struct
类型使用方法protocol
,该方法将是静态方法。如果我错了,你能告诉我哪里错了吗?
⬇️School
代码
struct SchoolIterator: IteratorProtocol {
private var schoolList: School
var idx = 0
init(_ school: School) {
self.schoolList = school
}
mutating func next() -> String? {
defer { idx += 1 }
guard schoolList.count-1 >= idx
else { return nil }
return schoolList[idx]
}
}
struct School: Sequence {
fileprivate var list = Array(repeating: "school", count: 100000)
var count: Int { return list.count }
subscript(_ idx: Int ) -> String? {
guard idx <= count-1
else { return nil }
return list[idx]
}
func makeIterator() -> SchoolIterator {
return SchoolIterator(self)
}
}
var schools = School()
for school in schools {
print(school)
}
解决方案
您的 for 循环转换为:
var schools = School()
var iterator = schools.makeIterator()
while let school = iterator.next() {
print(school)
}
注意这里没有什么是协议。schools
is of type School
, iterator
is of type SchoolIterator
, 所做的一切next
(如访问schoolList.count
,或 的下标schoolList
)也处理结构。关键是编译器可以准确地确定您的意思是哪个成员,因为它的(编译时)类型是一个结构。无需查找见证表。
比较一下,例如
func f<S: Sequence>(_ s: S) {
for thing in s {
...
}
/*
var iterator: S.Iterator = s.makeIterator()
while let thing = iterator.next() {
...
}
*/
}
f(School())
f(1..<100)
编译器将如何调度调用iterator.next()
?我特意添加了类型注释以清楚地说明发生了什么——这一次,编译器不知道next
你的意思。是IndexingIterator.next()
吗?或者SchoolIterator.next()
?或者SomeOtherIterator.next()
?请记住,我可以f
使用任何类型的Sequence
! S.Iterator
这就是为什么它需要在运行时查找实际类型的见证表- 无法确定next
调用哪个。
至于为什么for i in 0..<100
使用动态调度,嗯,乍一看,似乎有所有的结构:
let range: Range<Int> = 0..<100
var iterator: IndexingIterator<Range<Int>> = range.makeIterator()
while let i = iterator.next() {
...
}
但是,iterator.next
实际上是这样的:
公共变异函数 next() -> Elements.Element?{ if _position == _elements.endIndex { return nil } let element = _elements[_position] _elements.formIndex(after: &_position) return element }
_elements
定义如下:
public struct IndexingIterator<Elements: Collection> {
internal let _elements: Elements
_elements
可以是任何类型的Collection
,所以同样,我们在编译时不知道哪个成员_elements[_position]
或_elements.formIndex
指的是哪个成员。是Array.formIndex
吗?或者Set.formIndex
?我们只在运行时知道,当我们知道是什么时Elements
。
推荐阅读:https ://medium.com/@venki0119/method-dispatch-in-swift-effects-of-it-on-performance-b5f120e497d3
推荐阅读
- python - 在 PCA 中构成 PC1 的原始特征百分比
- java - 如何在运行时分析当前 AEM 对包的依赖关系?
- android - 如何将云语音中超过 1 分钟的音频片段转录为文本 API?
- javascript - 返回惰性求值表达式的函数的术语是什么?
- android - 模拟器预览中显示但设备中不显示的文本
- mysql - 将 MYSQL 行值转换为列名
- encryption - 查询包含使用 Jasypt 加密的列的表时,GORM 不返回数据。(圣杯)
- scala - 如何断言验证scala中案例类字段的访问权限?
- javascript - 单击时如何从选择菜单中灰显特定选项?
- charts - 如何在悬停 Google 地理图表上替换或删除国家笔划颜色?