3

假设我有一个从模块导出的函数,但模块多次使用该函数。

所以我写了一个别名,因为我在编码时很懒惰。

-export([get_toolkit/0]).

get_toolkit() -> 
    ... code ... code ... 
    ... code ... code ... 
    ... code ... code ... 
    {ok, Thing}.

tk() -> get_toolkit().

编译器是否优化别名?

谢谢

4

3 回答 3

5

我认为这将花费您一次间接费用。我这样说是因为我拿了这个代码

-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.
  • snip-it 中列出的第一个函数是“速记”函数,tk/0。
  • 第二个是调用get_toolkit/0的长函数,
  • 第三个是使用 tk/0 简写的简写函数

ASM 显示最后一个函数(使用 tk/0 的函数)调用 tk/0 ({call, 0, {f, 4}}),后者又调用 get_toolkit/0 ({call, 0, {f,2 }})。使用 get_toolkit/0 的函数直接调用 get_toolkit/0 ({call, 0, {f,2}})。

所以,我认为没有应用优化。

另外,我做了一些时间测试,似乎支持这个假设;)

于 2013-02-07T22:11:59.273 回答
3

(无法发表评论,因此必须将其包含在附加答案中...)

作为替代方案,您可以通过添加以下内容来告诉编译器内联函数:

-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的Inlining部分。

于 2013-02-11T21:56:18.503 回答
1

取决于您所说的优化是什么意思。一般来说,编译器会在运行时优化它知道模块和函数名称的调用,特别是如果函数在同一个模块中,所以我倾向于说是。

于 2013-02-07T19:31:22.260 回答