Erlang:递归循环的性能成本

Erlang: performance cost for recursive loop

我正在用 Erlang 编写一个简单的服务器程序。这是我的接受循环:

loop(Sock) ->
    {ok, Conn} = gen_tcp:accept(Sock),
    Handler = spawn(fun () -> handle(Conn) end),
    gen_tcp:controlling_process(Conn, Handler),
    loop(Sock).

这显然是一个递归函数。我的问题是:如果越来越多的客户端连接,我的函数堆栈会持续增长多长时间?这会影响我的应用程序的性能吗?

Erlang 处理两种递归函数:

  • 递归函数
  • 尾递归函数

您可以在 this link

上通过示例代码了解不同之处

但是让我们检查一下你的代码,如果你定义了你的代码

loop(Sock) ->
    {ok, Conn} = gen_tcp:accept(Sock),
    gen_tcp:controlling_process(Conn, Handler), 
    loop(Sock),
    spawn(fun () -> handle(Conn) end).

那将是一个递归函数,最终它会溢出堆栈,因为执行的最后一行不是调用 loop 函数,而是您定义代码的方式

loop(Sock) ->
    {ok, Conn} = gen_tcp:accept(Sock),
    Handler = spawn(fun () -> handle(Conn) end),
    gen_tcp:controlling_process(Conn, Handler),
    loop(Sock).

最后执行的代码再次调用loop函数(不一定是最后一行代码,但必须是最后执行的函数,称为tail recursion 而且它不会填满堆栈。Erlang 到处都在使用这种机制,它是 erlang 服务器的基础。

关于 erlang 中的递归函数何时停止工作的原始问题,这实际上取决于您 运行 beam 机器的方式,递归函数上定义的代码,并且很可能您应该不用担心,因为如果你错误地编写了一个溢出堆栈的递归函数,它会终止进程,它会被记录下来,主管会重新启动服务器,最终你会注意到错误并进行修复。