让我们聊聊Erlang虚拟机的设计理念

使用Erlang很久,一直想为什么要设计Port,但是最近深入的阅读了Erts的代码后有了一些想法。

当我从erlang:open_port这个函数开始跟踪这个Port创建的时候,发现Port在创建的时候并没有被调度到scheduler上或者专用的线程上去,而是简简单单的几个数据结构。那么Port是怎么被调度到scheduler上的呢?通过代码阅读,我从erl_port_task.c文件中找到了erts_port_task_schedule函数,正是这个函数将Port调度到了scheduler上的。之后我发现在erl_check_io的时候也会调用erts_port_task_schedule这个函数。从而我得到下面的结论:

  1. Erlang的Port并不是一直在调度器的队列中的。

  2. Erlang的Port在被Erlang进程通过erlang:controll和erlang:command函数发送命令时,才会被放入RunQueue。

  3. Erlang的Port如果向erts中注册了IO任务,则在scheduler进行erl_check_io的时候才会被放入RunQueue。

  4. Erlang的Port和Erlang进程类似,可以进行link和monitor,从而达到link的进程退出Port也随之退出。

  5. Erlang的Port总有一个connected的Erlang进程,这个Erlang进程是Port默认发送消息的进程。

至此我们可以看出Erlang虚拟机的基本理念如下:

  1. Erts是以scheduler为核心的,一个全力执行任务队列中任务的机器。

  2. Erts不将复杂的IO处理当作整个虚拟机的一部分,而是将IO事件分配当作整个虚拟机的一部分。

  3. Erts将任务分为两类,一类是OPCode执行(Erlang的进程),一类是IO任务的执行(Erlang的Port)。

Erlang运行时环境选择这样做,我认为有以下几个原因:

  1. 复杂的IO处理如果作为Erts的一部分,会引入大量的代码,同时对各个平台的兼容性很难保证。所以将IO分配作为Erts的一部分且将复杂IO的操作抽象为driver(Erlang的Port),这样会大大减少代码量和提高对平台的兼容性。

  2. 这样设计符合Erlang整体以进程和消息为中心的设计理念。因为在Erlang进程和IO操作分开,让IO任务化,这样Erlang调度器复杂度就降低了很多。在这种情况下,Erlang的进程就是和Erlang的IO操作都是任务队列上的一个个任务,方便调度和任务密取的进行。

总结下,Erts核心理念就是执行任务和调度任务,让整个系统的吞吐最大化。



你可能感兴趣的:(Erlang虚拟机,Port机制,IO任务化。)