[erlang-questions] Efficiency is passing a functin

Lukas Larsson lukas@REDACTED
Sun Sep 23 16:11:45 CEST 2012


When you do `fun myfunction` you are creating a fun which points to a
named function. What that text is referencing is that doing

F = fun myfunction/0,
F()

is slower that calling

myfunction()

directly.

So if you want absolute super speed of your lists:fold you should
write the loop yourself and call the function. The speed difference
between the two alternatives is usually not big enough to warrant the
extra code bloat for the minimal speed you gain.

Lukas

On Sun, Sep 23, 2012 at 3:45 PM, Jim Rosenblum <jrosenblum@REDACTED> wrote:
> Ulf,
>
> How do I reconcile your answer with the previous reference to:
> http://www.erlang.org/doc/efficiency_guide/functions.html#id67199  which
> seems to imply that Funs are significantly slower?
>
>
> On Sep 23, 2012, at 8:55 AM, Ulf Wiger <ulf@REDACTED> wrote:
>
>
> To begin with, your example won't compile, but the question is still valid.
>
> Consider this program:
>
> =================
> -module(foldtest).
> -export([f1/2, f2/2]).
>
> f1(Acc, Lst) ->
>     F = fun(A,B) -> my_function(A,B) end,
>     lists:foldl(F, Acc, Lst).
>
> f2(Acc, Lst) ->
>     lists:foldl(fun my_function/2, Acc, Lst).
>
> my_function(X, Acc) ->
>     [X|Acc].
> =================
>
> I believe this illustrates the question, but compiles and runs correctly.
>
> Eshell V5.9  (abort with ^G)
> 1> foldtest:f1([], [1,2,3]).
> [3,2,1]
> 2> foldtest:f2([], [1,2,3]).
> [3,2,1]
>
> Now, let's compile the code with `erlc -S foldtest.erl` (generating ASM
> code):
>
> {function, f1, 2, 2}.
>   {label,1}.
>     {line,[{location,"foldtest.erl",4}]}.
>     {func_info,{atom,foldtest},{atom,f1},2}.
>   {label,2}.
>     {allocate,2,2}.
>     {move,{x,1},{y,0}}.
>     {move,{x,0},{y,1}}.
>     {make_fun2,{f,14},0,0,0}.
>     {move,{y,0},{x,2}}.
>     {move,{y,1},{x,1}}.
>     {line,[{location,"foldtest.erl",6}]}.
>     {call_ext_last,3,{extfunc,lists,foldl,3},2}.
>
>
> {function, f2, 2, 4}.
>   {label,3}.
>     {line,[{location,"foldtest.erl",9}]}.
>     {func_info,{atom,foldtest},{atom,f2},2}.
>   {label,4}.
>     {allocate,2,2}.
>     {move,{x,1},{y,0}}.
>     {move,{x,0},{y,1}}.
>     {make_fun2,{f,12},0,0,0}.
>     {move,{y,0},{x,2}}.
>     {move,{y,1},{x,1}}.
>     {line,[{location,"foldtest.erl",10}]}.
>     {call_ext_last,3,{extfunc,lists,foldl,3},2}.
>
> As you can tell, the two alternatives generate identical code.
>
> The fun is compiled into a regular function, albeit with a funny name, and
> calling it carries the same cost as calling a hand-written function.
> Actually instantiating a fun context carries a slight overhead depending on
> the number of variables that need to be imported into the context (in this
> case, zero). There will be one level of indirection in both cases.
>
> BR,
> Ulf W
>
> On 23 Sep 2012, at 02:07, James Rosenblum wrote:
>
> Is there an appreciable difference in these two ways of passing a function?
>
> F = fun(A,B) -> my_function(A,B) end.
> lists:map(F, Lst)
>
> vs.
>
> -export([my_function/2]).
>
> lists:map(fun my_function/2, Lst)
>
>
> Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.
> http://feuerlabs.com
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>



More information about the erlang-questions mailing list