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 机器的方式,递归函数上定义的代码,并且很可能您应该不用担心,因为如果你错误地编写了一个溢出堆栈的递归函数,它会终止进程,它会被记录下来,主管会重新启动服务器,最终你会注意到错误并进行修复。
我正在用 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 机器的方式,递归函数上定义的代码,并且很可能您应该不用担心,因为如果你错误地编写了一个溢出堆栈的递归函数,它会终止进程,它会被记录下来,主管会重新启动服务器,最终你会注意到错误并进行修复。