[erlang-questions] BEAM micro-optimization: term comparison (> 0) versus pattern-matching

John Doe donpedrothird@REDACTED
Sun Apr 16 16:24:02 CEST 2017


You are right. In the compiled code comparison is slightly faster than
matching.

-module(test).

-export([test/2]).

test(N, T) ->
 L = lists:seq(1, 10000000),
 F1 = fun() -> lists:foreach(fun(_) -> case T of {success, Z}
-> Z; {error, Z} -> Z end end, L) end,
 erlang:display(timer:tc(F1)),
 F2 = fun() -> lists:foreach(fun(_) -> case N of X when X > 0
-> X; _ -> N end end, L) end,
 erlang:display(timer:tc(F2)).

1> c(test).
{ok,test}
2> test:test(-1, {error, -1}).
{292472,ok}
{250206,ok}








2017-04-16 13:58 GMT+03:00 José Valim <jose.valim@REDACTED>:

> John, did you measure in the shell?
>
> Code in the shell is evaluated and it won't give the same result as if the
> code would be compiled as part of a module.
>
> Ideally you want to define a module, compile it, and then execute a
> function that runs the benchmarking.
>
> *José Valim*
> www.plataformatec.com.br
> Skype: jv.ptec
> Founder and Director of R&D
>
> On Sun, Apr 16, 2017 at 1:53 AM, John Doe <donpedrothird@REDACTED> wrote:
>
>> Just've checked, the first one is approx 2 times faster on 19.1.6
>> 1> L = lists:seq(1, 1000000).
>> 2> N = -1.
>> 3> T = {error, -1}.
>> 4> F1 = fun() -> lists:foreach(fun(_) -> case T of {success, Z} -> Z;
>> {error, Z} -> Z end end, L) end.
>> 5> F2 = fun() -> lists:foreach(fun(_) -> case N of X when X > 0 -> X; _
>> -> N end end, L) end.
>> 6> timer:tc(F1).
>> {1089950,ok}
>> 7>
>> 7> timer:tc(F2).
>> {1870456,ok}
>>
>> 2017-04-15 21:13 GMT+03:00 Mikael Pettersson <mikpelinux@REDACTED>:
>>
>>> Suppose a frequently called function returns a positive integer (always
>>> a fixnum)
>>> and a boolean "success" or "failure" indicator (even in the failure case
>>> the return
>>> value is significant and will be used).  Which is better from a
>>> performance
>>> perspective:
>>>
>>> 1. Tag the return value, {success, X} or {failure, Y}, and have callers
>>> pattern-match
>>>    on that
>>>
>>> or,
>>>
>>> 2. Indicate failure by negating Y, and have callers match on
>>>
>>>       X when X > 0 -> success case;
>>>       MinusY -> failure case % MinusY =< 0 is implicit
>>>
>>> Option 2 avoids the consing overheads of option 1, but I'm worried that
>>> the X > 0
>>> guard may be less optimized than a plain structural pattern-match.  The
>>> last time
>>> I checked, term-comparisons would check inline for identity, and
>>> otherwise call
>>> the general cmp() function which would then do a lot of type-casing.
>>>
>>> In my pure Erlang code I'm using option 1, but I'm reimplementing the
>>> function
>>> as a NIF, and would like to avoid the consing overheads is that's indeed
>>> better.
>>>
>>>
>>> /Mikael
>>> _______________________________________________
>>> erlang-questions mailing list
>>> erlang-questions@REDACTED
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170416/7d3b6f42/attachment.htm>


More information about the erlang-questions mailing list