erlang调度器(转)

作者:CSSS
链接:https://www.zhihu.com/question/24732869/answer/56127705
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

具体Erlang调度器工作原理相当复杂,单个进程层面、多个调度器层面等都有特定的控制办法。大概可以分为 Erlang抢占式调度、进程资源隔离、进程优先级管理和调度器之间的管理几个部分。
1. Erlang 抢占式调度
Erlang实现公平调度基于Reduction Budget(运行次数限制)这一概念。
每一个进程(普通和端口)创建时初始reduction budget值为2000,任何Erlang系统众的操作都会消耗部分budget。当budget降低到0,该进程交出CPU使用权,被其他进程抢占。
函数调用、调用 BIF、进程堆垃圾回收、ETS 读写、发消息(目标邮箱堆积的消息越多,消耗越大),均会造成budget不同程度减少。例如函数调用,budget -1;发消息,根据对端mail box长度正比减少 。当mailbox长度过大时,budget消耗增加,中止发送消息。
2. 进程资源隔离
每个Erlang进程由PCB(进程控制块),stack (存储零散数据和指针信息)以及heap (存储复合数据,例如元组/表单/大整数)组成。 Erlang进程是虚拟机级别的进程,非常轻量,初始化时只有2K左右。 由于Erlang进程资源的隔离性,每个进程的进程内存都会被独立GC,即对单个进程垃圾回收不会STW(stop the world)。
Erlang进程的private heap结构设计保证了进程之间的资源隔离,独立的GC保证了尽量少的垃圾回收抖动。当进程退出时,内存直接回收。这些机制都保证了Erlang的高可用性和软实时性。
erlang调度器(转)_第1张图片

3. 进程优先级管理
上文提到Erlang调度器基于 Reduction Budget=2000的原理。当进程的reduction quantum被消耗完毕,或者进入wait状态,则进程停止。
每个调度器拥有3条队列,分别为:最大优先级队列,高优先级队列,正常+低优先级队列。接口(ports)另有一条队列。Run queue length即每条队列内进程或接口的数量,其值是进程分配migration的依据之一。为了确保每个进程分配时间均匀和按顺序执行,Erlang采用 Round-Robin算法。
4. 调度器之间的管理
调度器的另一个重要功能为通过跨进程/跨核的work sharing/stealing来平衡负载。
在每个balance check周期内,其中一个调度器(简称Scheduler A)会审查所有其他调度器的负载情况,以此决定下个周期的活跃调度器数量。同时,Scheduler A计算出迁移限制量 (migration limit),即每个优先级队列可以支撑的迁移进程/接口数量。除此之外,Scheduler A也会给出迁移路线。
在迁移和执行关系确定之后,活跃和非活跃的调度器之间通过其工作状态互相转换。例如,当系统全速运转时,拥有较少工作量的调度器将承担主要执行任务。下图为调度器的状态转换规则。
erlang调度器(转)_第2张图片
正是通过极其精密的调度系统,Erlang能够保证在各种极端环境下真正执行抢占式多任务处理,精细化实现软实时概念。这在我们调研的多种语言中是最适用于高并发软实时场景的。其他基于协作的语言和系统,包括node.js, go, python等都无法与之匹敌。

你可能感兴趣的:(erlang)