山大软工实践hive(8)-DefaultWalker的starkWalking方法以及ForwardWalker的walk方法

2021SC@SDUSC

山大软工实践hive(8)-DefaultWalker的starkWalking方法以及ForwardWalker的walk方法

接着上一次starkWalking

看startwalking方法,这是接口Graphwalker中唯一的接口
在这里插入图片描述
其中这里的ogw为ForwardWalker,ForwardWalker继承了DefaultWalker,而这个方法就在这个DW里面实现
在这里插入图片描述
其中输入的是所有头结点
toWalk为List< Node >
每次从列表里index=0的地方获得一个头结点并从列表移除,然后进行walk方法
接下来的注释内容暂不理解
然后当输出结果不为null(可能其他优化器调用时需要输出)并且调度器列表包括这个节点会向结果集放入该节点(调度器出现的频率相当地高,后面要去调查这个是干什么的)
在这里插入图片描述
这个retMap是一个IdentityHashMap,在这个类里,只在下面的方法放入过数据
(IdentityHashMap不同在于用的“==”比较,也就是说对象之间比较地址,而不是hashcode)
在这里插入图片描述
getChildren返回的是子节点列表
可以看到,方法对该节点的子节点用调度器做了评估,把结果存在retMap里(这里的dispatcher应该是DefaultRuleDispatcher,暂不深入)
在这里插入图片描述
再看walk方法
在这里插入图片描述
把当前头结点push到stack里面
下面部分都在while栈不空循环里

{
	从栈中获取一个节点
	当节点没有子节点或节点的所有子节点在调度器的列表(hashmap)里时
		如果调度器hashmap不包含该节点
			调用dispatch方法并向op队列加入该节点
		从栈中去除该节点
	
	取出该节点的所有子节点,判断每一个是否在调度器列表里,在则向栈压入该节点	
}

其中里面的二参数dispatch方法如下(三参数dispatch是Dispatch类的方法,暂不讨论)
在这里插入图片描述
这个dispatchAndReturn就是上面说的唯一向retMap添加元素的方法,调用的三参数dispatch

所以是starkWalking()=>walk()=>dispatch()=>dispatchAndReturn()=>retMap添加元素

总的顺序是:

  1. 不断从头节点列表取一个节点,开始walk方法,先把头节点入栈。然后如果栈不空,则读取一个节点。
  2. 如果该节点有子节点均被调度器调度过(retMap里没有)且该节点没有被调度过,则把该节点放入opQueue,执行dispatchAndReturn,通过三个参数(该节点,walk里的opStack栈的情况,该节点的子节点)执行调度方法获得返回值,并把该节点与结果以键值对形式存放在retMap里,并执行opStack.pop()与continue。
    (上面代表着,通过不同的头节点重复的遍历某个节点不会重复安排调度)
  3. 反之遍历该节点的所有子节点,当读到一个没有被调度过的节点,则入栈。并且开始下一个while循环。这样读完所有头节点后可以遍历DAG
  4. 每walk完一次,就看是否需要输出,需要则从retMap里把结果放入nodeOutput里(一个hashmap)
  5. 头节点被取完后,如果需要输出,还要向输出结果(nodeOutput)把opQueue的节点不断放入,并清空了opQueue(其中,opQueue是显然的存储着节点被使用调度方法的先后顺序,不过由于输出结果是hashmap,所以并不重要)

ForwardWalker的walk

不过,由于此优化器用的是ForwardWalker,它的walk方法还与这个默认Walker不一样,如下
在这里插入图片描述
其中allParentsDispatched(nd)是用于判断该节点的所有父节点是否被调度了(dispatch方法)
在这里插入图片描述

由于这个方法看着莫名其妙,所以我先顺序地读一下进行推理

	第一个if让我疑惑的点在于为什么nd可能等于opStack.peek(),先向下看
	第二个if语句,如果某节点所有父节点均被调度过了,则可以开始尝试对此节点调度,并从栈中移除该节点,然后return,如果没有都被调度,
则跳过,可能是希望先把该节点的所有父节点调度
	最后的if语句外的部分,不论怎样,会向toWalk的头部添加该节点,并调用addAllParents(nd),它的作用是从toWalk里去除所有该节点
的父节点,然后不断的读取父节点把它们添加在toWalk的头部

addAllParents(nd)
在这里插入图片描述

也就是说,当一个节点存在父节点没被调度,就会向toWalk添加它的父节点,直到它的所有父节点被调度,才会walk它

两种walk的区别

可以看见,默认walk优先让子节点先被调度,然后才是父节点。而ForwardWalker是先调度父节点,再子节点。目前不知道理论上的区别。

找寻opstack的踪迹(结果是没被dispatcher改动)

这一步其实是之前对两个walk方法的理解出了问题,所以尝试向下看导致的,不过opStack是用于计算调度的一大变量,不能忽视,这里面就能看到有如cost方法计算开销?
而且我去看了dispatcher是否对opstack有所影响,结果是没有,如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
先跟踪Rules
在这里插入图片描述

在这里插入图片描述
是RuleRegExp类的cost方法
在这里插入图片描述
其中对stack有调用的方法都长一个样,并没有对其更改,如下
在这里插入图片描述
再看.process,回到了优化器,不过这个更厉害,完全没使用过栈
在这里插入图片描述

接下来

去看dispatcher相关内容,思考这两种walk下opStack的结构与区别

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值