假设我有一个从模块导出的函数,但模块多次使用该函数。
所以我写了一个别名,因为我编码的时候很懒。
-export([get_toolkit/0]).
get_toolkit() ->
... code ... code ...
... code ... code ...
... code ... code ...
{ok, Thing}.
tk() -> get_toolkit().
编译器是否优化别名?
谢谢
我认为这会花费你一个间接的时间。我这么说是因为我拿了这个代码
-module(testit).
-export([get_toolkit/0, long/0, short/0]).
get_toolkit() ->
_ = lists:seq(1,100),
{ok, thing}.
tk() ->
get_toolkit().
long() ->
get_toolkit(),
{ok, thing2}.
short() ->
tk(),
{ok, thing3}.
并通过 erlc -S testit.erl 生成 ASM,这给了我
SNIP
{function, tk, 0, 4}.
{label,3}.
{line,[{location,"testit.erl",8}]}.
{func_info,{atom,testit},{atom,tk},0}.
{label,4}.
{call_only,0,{f,2}}.
{function, long, 0, 6}.
{label,5}.
{line,[{location,"testit.erl",11}]}.
{func_info,{atom,testit},{atom,long},0}.
{label,6}.
{allocate,0,0}.
{line,[{location,"testit.erl",12}]}.
{call,0,{f,2}}.
{move,{literal,{ok,thing2}},{x,0}}.
{deallocate,0}.
return.
{function, short, 0, 8}.
{label,7}.
{line,[{location,"testit.erl",15}]}.
{func_info,{atom,testit},{atom,short},0}.
{label,8}.
{allocate,0,0}.
{line,[{location,"testit.erl",16}]}.
{call,0,{f,4}}.
{move,{literal,{ok,thing3}},{x,0}}.
{deallocate,0}.
return.
ASM 显示最后一个函数(使用 tk/0 的函数)调用 tk/0 ({call, 0, {f, 4}}),而 tk/0 ({call, 0, {f, 4}}) 又调用 get_toolkit/0 ({call, 0, {f, 2}})。使用 get_toolkit/0 的函数直接调用 get_toolkit/0 ({call, 0, {f,2}})。
所以,我认为没有应用优化。
另外,我做了一些时间测试,似乎支持了这个假设;)
(无法发表评论,因此必须将其包含在附加答案中......)
作为替代方案,您可以通过添加以下内容来告诉编译器内联该函数:
-compile({inline,[tk/0]}).
然后这个
{function, get_toolkit, 0, 2}.
...
{function, tk, 0, 4}...
{call_only,0,{f,2}}.
...
{function, short, 0, 8}...
{call,0,{f,4}}.
...
将成为
{function, get_toolkit, 0, 2}.
...
{function, short, 0, 6}...
{call,0,{f,2}}.
这完全消除了
tk/0
函数,因为它没有导出,内联代码直接调用 get_toolkit
。
这记录在http://www.erlang.org/doc/man/compile.html,第内联部分。
取决于您所说的优化是什么意思。一般来说,编译器会在运行时知道模块和函数名称的情况下优化调用,特别是如果函数位于同一模块中,所以我倾向于说是。