2013-02-07 30 views
3

假設我有一個從模塊導出的函數,但模塊多次使用函數。在Erlang中優化了別名函數

所以我寫了一個別名,因爲我很懶,當我編碼。

-export([get_toolkit/0]). 

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

tk() -> get_toolkit(). 

編譯器是否優化了別名?

謝謝

+0

如果你的代碼因爲額外的函數調用而變慢,我會爭辯說你的代碼的其餘部分已經完全優化了。總之,沒關係。 –

+0

我不知道,我沒有測量我的代碼的執行時間,這是更多關於知識和最佳實踐:) – niahoo

+0

談到最佳實踐我認爲你應該使用全名(清晰度)。如果您發現它可以節省大量時間來使用快捷方式,那麼您總是可以自動替換它。 –

回答

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. 
  • 中列出的第一個功能剪斷,它是「短手「功能,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}})。

所以,我認爲沒有優化應用。

而且,我做了一段時間的測試,其似乎支持這一假說;)

+0

感謝您的演示:)我將使用宏並查看ASM – niahoo

+0

@Soup d'Campbells關於使用-define宏(tk,get_toolkit())的建議。可能是做你想做的最好的方法 – Jr0

1

取決於你的意思是經過優化。一般來說,編譯器會在運行時知道模塊和函數名的地方優化調用,特別是如果函數在同一個模塊中,所以我傾向於說是。

+0

我的意思是:「調用tk()而不是get_toolkit()不會花費更多的CPU/RAM/...」:) – niahoo

+1

由於第二功能,它可能需要花費一個或兩個週期來評估。如果你想避免使用編譯器定義:'-define(tk,get_toolkit())。' –

+0

好吧,這就是我現在要做的,看起來很簡單。 – niahoo

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}}. 

,因爲它是不出口和內聯的代碼直接調用get_toolkit從而徹底消除了tk/0功能。

這記錄在http://www.erlang.org/doc/man/compile.html,部分內聯

+0

非常有趣,謝謝 – niahoo