庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

Kilim实现浅析(一)

Posted on 2010-09-17 12:05 dennis 阅读(10500) 评论(5)  编辑  收藏 所属分类: java源码解读

    Kilim是一个Java的actor框架,让你可以在JVM里使用基于协程的actor模型,bluedavy曾经介绍过,这里不再赘言。这篇blog的目的在于分析下kilim实现的基本原理,看看怎么在JVM上实现协程。

    在一些语言层面上支持协程的语言,如lua、ruby,都是直接在VM级别支持协程,VM帮你做context的保存和恢复。JVM没有提供这样的指令来保存和恢复方法栈的状态,因此kilim的实现还是需要在bytecode级别做文章。首先,试想下,如果是你来实现协程,你会怎么做?协程的两个基本原语resume和yield,resume运行协程,yield让出执行权,下次resume的时候会从yield的地方重新执行,并且context保持不变。可见,你需要做这么几个事情:
1、在yield的时候保存当前context。
2、在resume的时候恢复context,并根据pc计数来决定从哪里恢复执行。
3、半协程的实现来说,还需要一个调度器来调度所有协程。
4、为了做到用户代码透明,可能需要某种手段去修改用户代码,自动帮你做上面三个事情。

    kilim的实现就是干了这么几个事情:
1、利用字节码增强,将普通的java代码转换为支持协程的代码。
2、在调用pausable方法的时候,如果pause了就保存当前方法栈的State,停止执行当前协程,将控制权交给调度器
3、调度器负责调度就绪的协程
4、协程resume的时候,自动恢复State,根据协程的pc计数跳转到上次执行的位置,继续执行。


    下面是来自kilim文档的一个例子,同一段代码,在字节码增前前后的变化:

   
左边是原始代码,右边是通过字节码增强后的代码。其中h方法是pausable的,也就是说可能被暂停阻塞的,g方法因为调用了h这个方法也变成了pausable。

首先看,原始的h方法是没有传入任何参数的,增强后的代码,多了个参数Fiber,指向当前的协程,同样,g方法本来只有一个参数n,现在在后面也多了个Fiber类型的参数,同样是指向当前执行的协程。

其次,在原始的g方法里,一旦调用,马上进入一个for循环。但是在增强后的代码,多了个switch派发的过程,这就是前面提到的,根据当前的Fiber的pc计数,跳转到上一次执行的地方执行。如果是第一次resume,也就是启动协程,那么就将初始循环的i设置为0,进入原始代码的循环部分。Fiber有一个pc计数,称为程序计数器,用于指向恢复context的时候需要跳转到位置。

第三,在g方法里调用h这个可被暂停阻塞的方法的时候,在h方法前后多了一些调用:
f.down();
h(f);
f.up();

kilim的Fiber将每个pauseable方法的调用组织成一个栈,每个pauseable方法都有一个activation frame,翻译过来可以称为活动栈帧,这个栈帧记录了当前的栈的State,注意这个栈跟java本身的方法调用栈区分开来,一个是VM层面的,一个是kilim框架层面的。这里的down方法就是将栈向下延伸,表示将调用一个pauseable方法,并且设置当前State和pc计数。
调用了down之后,才是调用实际的h方法,最后还要调用一次up,顾名思义,就是说一次pauseable方法调用完成,fiber的活动栈要递增一层,回到上一层。但是h方法调用可能出现四种情况:
1、正常的顺利返回,没有状态需要恢复,所谓NOT_PAUSING__NO_STATE
2、也是正常返回,有状态需要恢复,也就是NOT_PAUSING__HAS_STATE
3、h方法暂停阻塞,当前没有保存状态,需要保存状态,这是第一次暂停的时候,称为PAUSING__NO_STATE
4、h方法暂停阻塞,当前已经有状态,不需要保存状态,这是第一次暂停之后的resume再次暂停,称为PAUSING__HAS_STATE,通常不需要处理什么。

第四,可以看到,在up之后,就要根据up返回的上述4种状态执行不同的逻辑:
if (f.isPausing){
    
//第一次暂停,没有状态
   if (!f.hasState){
     
//new一个State_I2,并保存i和n
     f.state = new State_I2(i,n);
    
//记录pc,还记的前面的switch吗?
     f.pc = H1;
   }
   
return;
else if (f.hasState)
   
//正常返回,有状态需要恢复,恢复i和n
   State_I2 st = (State_I2) f.state;
   i 
= st.i1; n = st.i2;
}


这里没有处理NOT_PAUSING__NO_STATE和PAUSING__HAS_STATE,因为这两种情况在这里不需要处理。


    通过上面的分析,我想大家对kilim的实现应该已经有一个很基本的认识。下一步,我们分析一个实际的代码例子,查看整个运作流程。
 

评论

# re: Kilim实现浅析(一)  回复  更多评论   

2010-09-17 13:08 by arbow
老大终于出马了,赞!

# re: Kilim实现浅析(一)  回复  更多评论   

2010-09-17 23:09 by glf
好文章!!!

# re: Kilim实现浅析(一)  回复  更多评论   

2010-09-26 11:11 by thomas sabo onlineshop
Stay long received slightly larger women generally wear ear clip, or earrings, or drape type, color of the earrings is appropriate, because income itself shawls face contours and lines of influence, so stay close to the length restrictions on wearing earrings less, but in general a more visible and have a certain size of earrings as well, small earrings are very limited.

# re: Kilim实现浅析(一)  回复  更多评论   

2012-12-05 22:56 by XCC
呜呜,木有后文了?

# re: Kilim实现浅析(一)  回复  更多评论   

2015-03-24 09:43 by xsank
内容略少啊~

只有注册用户登录后才能发表评论。


网站导航: