BRPC的精华都在bthread上啦(四):尾声

关于bthread的源码剖析洋洋洒洒在知乎也已经发表了三篇文章,在公众号号中将文章重组拆解后也已经发表了五篇。其实这类源码剖析类的文章从来都不好写。首先因为代码的冗杂,在解读的时候没办法找到一个”线性“视角,可以一以贯之的解读下来。比如讲A知识点的时候就会涉及到B,但展开讲B,整篇文章就会缺少主线,不去讲B,会可能造成讲解A到时候有些含混不清。又或者有一些brpc源码之外的基础知识,不确定读者是否都有足够的知识背景,所以是否要扩展解读也要费思量。
凡此种种,如何清晰地划分每一篇文章的边界,确定好每部分知识点的详略,确实让笔者费了不少功夫。如今bthread源码的主要解读都已经完毕,后续可能会涉及到一些细节补充。但主体确实已经完结,当然这并不是brpc源码解读系列的完结,因为brpc中不仅有bthread,还有很多其他可以值得讲解的东西。
如果你认真读完了笔者前面的那些文章,不知道你会不会产生一些疑问。可能我写的东西你都能看懂,但对于bthread还是有些疑问。没关系,质疑是学习的最好帮手,要善于提问,用于提问。下面我试着站在大家的角度,来提出一些FAQ,从而帮你更好地观察bthread理解上的任督二脉!

1. bthread_make_fcontext()虽然传入了栈大小,但是却没有被用到?

context = bthread_make_fcontext(storage.bottom, storage.stacksize, entry);

bthread_make_fcontext()最终会调用汇编函数make_stack(),其中用到了第一个参数(栈底),却没有用到栈大小。那么你是否有疑问,如果没有用到栈大小,那么是不是前面给bthread设置栈大小的属性参数就没有用呢?
非也非也。这里虽然汇编函数内确实没有用到栈的大小,但是storage.bottom其实已经是bthread可用的栈的最高地址了。回顾bottom的分配策略我们可知:

s->bottom = (char*)mem + memsize;

分配的栈大小确实是和bthread设置栈大小的属性参数有关的,然后这里返回的bottom是最高地址。也就是说时间在栈切换过去执行具体的协程任务的时候,由于栈是自高向低分配的,所以只要你使用的栈空间不超过大小就是OK的。在新局部变量分配的时候并没有进行边界检查,这在C语言里面亦是如是。当你使用的栈空间超过的时候,这里确实也会越界。
我曾经遇到过使用一个某个第三方库,会导致程序会core掉,归根结底是因为我设置的的栈大小是SMALL的,而这个库用到的栈空间比较多,改成NORMAL之后core解决。
2. 为什么要用汇编做任务切换,让worker(pthread)不停的从任务队列里取出任务去执行不就好了么?
看完前面的文章你可能会疑惑,Task已经封装到任务队列里了(rq,remote_rq),直接遍历队列取出任务,执行其中的回调函数就OK啦。干嘛要用汇编做一套make_stack和jump_stack呢?
我可以理解你的想法,在没有协程概念之前,很多线程池的涉及都如你这般,包括work stealing也可以被普通的线程池采纳。但是这里你永远要记住bthread的协程属性。所谓协程就是可以被中断的,也就是说你的bthread回调函数可以执行一半就退出worker,然后让给其他的bthread任务,等后续再唤醒回来继续执行刚才的运行了一半的任务。
这里的中断与否,其实就是看你的回调函数中是否有涉及到IO。比如brpc的Channel操作。如果你在通过RPC访问其他的brpc服务或者HTTP服务或者Redis等,这些操作都会让你的bthread退出,解除对worker的占用。待到下游response返回之后,才继续找到一个闲置的worker来处理你运行了一半的任务。这个中细节其实也颇为复杂,后续我会开篇去讲Channel的CallMethod与bthread的关联。

3. bthread适合做什么与不适合做什么

通过bthread,我们可以很方便的实现一个并行的调度库,我在工作中确实有见到过基于bthread实现的并行调度库,比如实现一个DAG在线调度引擎。借助于强大的bthread,我们只需要对于bthread_start_background()调用和封装一下就能实现。最复杂的部分brpc已经帮我们做了。
但诚然如此,我们还是要知道,bthread主要还是在充分利用的网络IO时的计算资源,通过M:N的协程来实现CPU利用的最大化。如果你的程序不是IO密集型的,只是单纯的计算密集型的,你当然也可以通过bthread来做并行化(比如for循环顺序处理无10000个元素,可以做出并行化的),但你需要知道这种场景使用bthread并不会比那些老牌的并行计算库更有优势,比如OpenMP、TBB等。

bthread支持类似omp的并行计算的方法 · Issue #965 · apache/incubator-brpc

4. 其他问题

其他问题欢迎提问
欢迎关注我的公众号:编程往事


http://
weixin.qq.com/r/EXUyKm7
E3TOirSpJ9yAD

(二维码自动识别)