1. IndexedRDDPartion構建過程
- 調用構建函數
val vp = IndexedRDDPartition(Iterator((0L, 1), (1L, 1)))
- 這裏會調用IndexedRDDPartition 的apply 方法。
def apply[V: ClassTag](iter: Iterator[(Id, V)]): IndexedRDDPartition[V] = {
// 申請PrimitiveKeyOpenHashMap的hash表
val map = new PrimitiveKeyOpenHashMap[Id, V]
// 將iter數據寫入hash表中
iter.foreach { pair =>
map(pair._1) = pair._2
}
// new一個新的IndexedRDDPartition對象作爲返回值
// 3個參數依次對應:index、values、mask
new IndexedRDDPartition(
ImmutableLongOpenHashSet.fromLongOpenHashSet(map.keySet), // index
ImmutableVector.fromArray(map.values), // values
map.keySet.getBitSet.toImmutableBitSet) // mask
}
2. index構建過程
- index 構建函數調用
// 這裏實際是調用ImmutableLongOpenHashSet的fromLongOpenHashSet方法
ImmutableLongOpenHashSet.fromLongOpenHashSet(map.keySet) // index
- fromLongOpenHashSet 方法
def fromLongOpenHashSet(set: OpenHashSet[Long]): ImmutableLongOpenHashSet =
new ImmutableLongOpenHashSet(
ImmutableVector.fromArray(set.data), //調用fromArray方法將對應節點的值傳進去
set.getBitSet.toImmutableBitSet,
-1,
set.loadFactor) // loadFactor默認值爲0.7
3. fromArray方法
- fromArray 方法定義
def fromArray[A: ClassTag](array: Array[A]): ImmutableVector[A] = {
// 再掉3個參數的fromArray方法,0表示起點下標
fromArray(array, 0, array.length)
}
def fromArray[A: ClassTag](array: Array[A], start: Int, end: Int): ImmutableVector[A] = {
// new一個ImmuableVector對象
// 該對象第一個參數是樹的大小
// 第二個參數是樹的根節點
new ImmutableVector(end - start, nodeFromArray(array, start, end))
}
- nodeFromArray 方法構建這棵樹
private def nodeFromArray[A: ClassTag](array: Array[A], start: Int, end: Int): VectorNode[A] = {
val length = end - start
if (length == 0) {
emptyNode
} else {
val depth = depthOf(length) // length個節點需要存儲的樹的高度,高度從0開始
if (depth == 0) { // 一層就可以存的下,一層大小爲32,說明節點個數小於等於32,調用LeafNode構建這個存儲
new LeafNode(array.slice(start, end))
} else {
val shift = 5 * depth // 左移的位數,從根節點出發
val numChildren = ((length - 1) >> shift) + 1 // 獲取根節點下子節點數目
val children = new Array[VectorNode[A]](numChildren) // new一個類型爲VectorNode[A],長度爲numChildren的數組
var i = 0
while (i < numChildren) { // 遍歷子節點
val childStart = start + (i << shift) // 子節點起始點位置
var childEnd = start + ((i + 1) << shift) // 子節點終止點位置
if (end < childEnd) { // 修正最後一個節點的終止點位置
childEnd = end
}
children(i) = nodeFromArray(array, childStart, childEnd) // 遞歸調用
i += 1
}
// 程序返回值就是下面這個InternalNode
// InternalNode是VectorNode的子類
// 這裏把子類遞歸返回給了父類,若直接返回children,children是一個Array類型的,不滿足返回值的類型
new InternalNode(children, depth)
}
}
}
- leafNode 構建葉節點
// 下面是一個主類構造器,構造器中有一個參數爲Array[A]
// 所以節點的最後一層存儲的就是一個數組
// 節點對外提供3個方法
private class LeafNode[@specialized(Long, Int) A: ClassTag](
children: Array[A])
extends VectorNode[A] {
require(children.length <= 32,
s"nodes cannot have more than 32 children (got ${children.length})")
override def apply(index: Int): A = children(index)
override def updated(index: Int, elem: A) = {
val newChildren = new Array[A](children.length)
System.arraycopy(children, 0, newChildren, 0, children.length)
newChildren(index) = elem
new LeafNode(newChildren)
}
override def numChildren = children.length
}
index 樹的構建過程已經結束,下面介紹bitset 的構建。
3. toImmutableBitSet方法
- toImmutableBitSet方法定義
// numBits表示需要多少個二進制位來存儲這些節點
// numBits大小就是節點數目
// words是二進制位轉成long型的數組時的數值
// words存儲也是用樹結構來完成的
private[spark] def toImmutableBitSet: ImmutableBitSet = {
new ImmutableBitSet(numBits, ImmutableVector.fromArray(words))
}
ImmutableVector.fromArray(map.values)
構建values 的樹形結構時可參考fromArray的構建index的過程。
至此,indexedRDD中三棵樹的存儲結構已經構建起來。關於IndexedRDDPartition的操作源碼分析,後面會繼續更新。
【待續】