3

モジュールからエクスポートされた関数があるとしますが、モジュールはその関数を何度も使用します。

私はコードを書くのが面倒なので、別名を書きました。

-export([get_toolkit/0]).

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

tk() -> get_toolkit().

コンパイラはエイリアスを最適化しますか?

ありがとう

4

3 に答える 3

5

1回の間接費がかかると思います。私はこのコードを取ったので、私はこれを言います

-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 です。
  • 2 番目は get_toolkit/0 を呼び出す長い関数です。
  • 3 番目は 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のセクション「インライン化」に記載されています。

于 2013-02-11T21:56:18.503 に答える
1

最適化の意味によって異なります。一般的に言えば、特に関数が同じモジュール内にある場合、コンパイラは実行時にモジュール名と関数名を知っている場合に呼び出しを最適化するので、私はそう言う傾向があります。

于 2013-02-07T19:31:22.260 に答える