erlang事件与线程有多重?

时间:2011-10-06 21:15:03

标签: events event-handling erlang

不确定这是否可行,但我正在阅读erlang,我正在看一下gen_event,我想知道将它用于完整的面向事件的编程的开销是多少,就像我在Node.Js中使用的那样示例

让事件处理任务与在erlang中生成新线程以执行相同任务的开销是多少。

感谢。

1 个答案:

答案 0 :(得分:8)

Erlang语言不暴露线程,它为您提供了Erlang进程。这些进程由Erlang运行时有效地调度到通常映射到CPU内核的OS线程上。它们重量轻(32位虚拟机上的内存占用量少于4kb,包括初始堆)并且是先发制人的,因此任何一个中的阻塞或大量CPU消耗都不会拒绝任何其他进程占用相当大的CPU时间。

所以不要害怕产生一个进程来处理你想要在你的系统中服务的每个请求 - 这是一个很好的初始设计,通常通过并行性提供良好的吞吐量,并且往往扩展到更多的核心/ cpus /节点更容易。

另一个好处是每个过程中的代码都可以用直接的程序方式编写:

%% 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资源以不同的速率运行。

从这里可以轻松添加对工作进程的监督,以便我们可以通过向spawn调用添加“Node”参数来创建工作人员,超时以重新启动单个请求失败,多机分布式处理,以便客户发出请求如果服务器过载或工作进程失败,则永远阻塞,等等。

通过在gen_event进程中使用多个处理程序,您无法获得上述代码能够实现的并行性。 gen_event代码更难以阅读,你必须自己交错请求,而不是让运行时为你做。


tl; dr:开销太低而另一个好处太大了,你通常(几乎总是)会产生一个进程,而不是在gen_event进程中尝试一次做多个事情。