Coroutine实现有感

来源:互联网 发布:淘宝 几次 五星 一个月 编辑:程序博客网 时间:2024/06/05 08:47

转载:http://www.douban.com/note/11552969/


今天在debug的过程中顺便翻看了wikipedia的Coroutine条目,简单了解一下coroutine的实现机制:
Coroutine其实仍然是串行运算,并不是真正意义上的并行计算。因此coroutine不会有传统并行计算的访问冲突。
Coroutine的实现方式可以分成两种,
第一种是借用C的Stack作为每个Coroutine的Stack空间,这种方法最为简单,在Unix/Linux下有getcontext(), setcontext(),windows下有fiber来使用或者使用setjump和longjmp。但是由于桟空间是又编译器来分配的,所以如果有大量的coroutine存在的情况下,会造成大量的桟空间的浪费,并且setjump和longjmp会造成很大的cache miss。
第二种是采用虚拟机的方式,对于大部分的虚拟机来说往往采用全局桟的方法来进行函数调用,例如lua,这种情况下创建多个coroutine的桟空间的开销就会非常小,并且保存和记录返回link的开销也会比较小,因为你不需要保存register set等等需要保证task切换的东西。

第一种实现方式往往称为Stackfull 如我最近在看的Io,而第二种方式则称之为stackless因为没有桟开销如stackless python,erlang

另外一个比较有意思的话题是coroutine yield的行为应该是什么样子的
我认为可以有两种方式:yield to last,这种情况下谁调用了这个coroutine执行函数,那么当被调用者yield的时候将会返回给这个调用方,这种方法可以实现安generator或者iterator,可以参考python,注意generator并不不需要进行task switch而是简单的返回结果

另外一种是yield to scheduler,就是scheduler将会知道当前有多少正处在yield状态的coroutine,然后根据优先级或者某种机制去resume这个coroutine的执行,这种方法可以扩展很多其他的并行函数,例如Sleep,BeNice,隐含的async io等等,据我所知Io和stackless python就是采用这种方式的实现。

但是这两种做法其实并不冲突,可以认为每个coroutine保存了一个yield to地址,当被其他coroutine resume的时候需要保存这个地址用来返回,但是要是被scheduler resume的时候这个地址并不需要被修改,例如:

Yield To Other:
coroutine Producer
    produce one product
    yield Consumer

coroutine Consumer:
     use one product
     yield Producer

Yield To Scheduler:
coroutine Producer
     produce one product
     yield

coroutine Consumer:
    use one product
    yield

while( Scheduler.yieldCoro > 1 ) Scheduler.getNextCoro resume

more complex one :)

coroutine Producer
     receive from network // async function, will yield this coro immediately
     yield Consumer // ok data is ready, let consume start

coroutine Consumer
      use one product
      sleep(30) // start to sleep, give producer a chance to receive from network
      yield Producer

while (Scheduler.yieldCoro > 1) Scheduler.getNetCoro resume // scheduler will skip consumer while it's sleep. and it won't ask producer to run again because after producer is at yield to consumer, not to yield to scheduler. that means only consumer able to resume the producer.


原创粉丝点击