Erlang事件与线程相比有多重?

4

不确定是否明智,但我正在研究Erlang,看了一下gen_event,想知道在完全面向事件的编程中使用它的开销,例如我在Node.Js中使用的方式。

在Erlang中,将任务交给事件处理程序与生成新线程执行相同任务之间的开销是多少?

谢谢。

1个回答

8
Erlang语言不使用线程,而是提供Erlang进程。这些进程由Erlang运行时高效地调度到操作系统线程上,通常将其映射到CPU核心。它们的内存占用量轻量级(32位VM的初始堆包括在内的内存占用小于4kb),并且是预抢占式调度的,因此其中任何一个阻塞或消耗大量CPU的进程都不会剥夺其他进程公平分享CPU时间的机会。
因此,不要担心在系统中为每个请求生成一个进程 - 这是一个很好的初始设计,通常通过并行处理获得良好的吞吐量,并且更容易扩展到更多核心/ CPU /节点。
另一个好处是,每个进程中的代码可以以直接的过程化方式编写:
%% Ask a server to perform a request and await the response from the worker.
request(Server, R) ->
    Server ! {new_request, R, self()},
    receive {response, Response} -> Response end.

%% Create a server.
start() ->
    spawn(?MODULE, server, []).

%% The server code
server() ->
    receive
        {new_request, R, Sender} ->
            %% Spawn a process to handle this request
            spawn(?MODULE, process_request, [R, Sender]),
        server()
    end.

%% The worker code
process_request(R, Sender) ->
    A = do_io(),
    B = do_cpu_bound_thing(A),
    C = do_io(C),
    Sender ! {response, C}. % Return the response to the sender
    %% Process shuts down cleanly here as there's nothing more to do. 

这里有两种进程,一种是单个中央服务器进程,负责接受新的请求;另一种是任意数量的工作进程,实际上执行工作。单个请求的错误不会影响服务器进程或其他工作进程,不同的工作进程可以根据IO和CPU资源运行在不同的速率下。
从这里开始,我们可以轻松添加对工作进程的监控,以便重新启动失败的单个请求,通过将“Node”参数添加到生成调用中来创建工作者的多机分布式处理,超时,使得进行请求的客户端如果服务器过载或工作进程失败则不会永久阻塞等等。
使用gen_event进程内部的多个处理程序无法获得上述代码所能实现的并行处理。gen_event代码将更加复杂,并且您必须自己交错请求,而不是让运行时为您完成。
简而言之:开销很低,而其他好处非常大,因此通常(几乎总是)应生成一个进程,而不是尝试在gen_event进程中同时执行多个任务。

谢谢,这基本上概括了一切。 - BRampersad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接