[erlang-questions] clarify: why bit syntax so slow + benchmark code

Per Gustafsson per.gustafsson@REDACTED
Fri Nov 16 16:09:35 CET 2007


Mateusz Berezecki wrote:
> Hello,
> 
> I have attached a benchmark at the end of this e-mail.
> It is a complete mystery to me why it performs so poorly.
> 
> Could please anyone share some ideas what is the
> background behind this behavior?
> 
> Example test results;
> 
> 24.1486134 seconds / 100 Mb (extracting 1 byte)
> 12.8946602 seconds / 100 Mb (extracting 2 bytes)
> 6.37089217 seconds / 100 Mb (extracting 4 bytes)
> 3.19605309 seconds / 100 Mb (extracting 8 bytes)
> 1.57278535 seconds / 100 Mb (extracting 16 bytes)
> 
> The code was compiled without +native flag.
> I don't understand why it performs so poorly .
> 
> The C code can do 600mb in 24 seconds while performing IO from disk
> while erlang code needs 24 seconds for 100mb while reading it from memory.
> 
> The million dollar questions is - Why ?
> 
> 
> regards,
> Mateusz Berezecki
> 


It is slow because for each iteration a two sub-binary structure (about 
5 words) is allocated. This will be optimized in the next release of 
Erlang/OTP, but your code is sub optimal anyway, if you want good 
performance you should write:

test1(<<>>) -> done;
test1(<<_A, Rest/binary>>) ->
        test1(Rest).

That is, you should not first pattern match and create a sub-binary and 
then match against that one.

Per

> P.S.
> Benchmark code
> 
> -module (benchmark).
> -export([bitsyntax/1, test1/1, test2/1, test4/1, test8/1, test16/1]).
> 
> test1(<<>>) -> done;
> test1(Bin) when is_binary(Bin) ->
>         <<A:1/binary, Rest/binary>> = Bin,
>         <<_A1:8>> = A,
>         test1(Rest).
> 
> test2(<<>>) -> done;
> test2(Bin) when is_binary(Bin) ->
>         <<A:2/binary, Rest/binary>> = Bin,
>         <<_A1:8, _A2:8>> = A,
>         test2(Rest).
> 
> test4(<<>>) -> done;
> test4(Bin) when is_binary(Bin) ->
>         <<A:4/binary, Rest/binary>> = Bin,
>         <<_A1:8,_A2:8,_A3:8,_A4:8>> = A,
>         test4(Rest).
> 
> test8(<<>>) -> done;
> test8(Bin) when is_binary(Bin) ->
>         <<A:8/binary, Rest/binary>> = Bin,
>         <<_A1:8,_A2:8,_A3:8,_A4:8, _A5:8, _A6:8, _A7:8, _A8:8>> = A,
>         test8(Rest).
> 
> test16(<<>>) -> done;
> test16(Bin) when is_binary(Bin) ->
>         <<A:16/binary, Rest/binary>> = Bin,
>         <<_A1:8,_A2:8,_A3:8,_A4:8, _A5:8, _A6:8, _A7:8, _A8:8, _A9:8, _A10:8,
> _A11:8,_A12:8, _A13:8, _A14:8, _A15:8, _A16:8>> = A,
>         test16(Rest).
> 
> bitsyntax(N) when is_integer(N), N > 0 ->
>         K = lists:seq(1, N * 16),
>         Bin = list_to_binary(lists:map(fun(X) -> <<X:8>> end, K)),
> 
>         io:format("Running tests for N = ~p.~n", [N * 16]),
>         {T1, _} = timer:tc(?MODULE, test1, [Bin]),
>         {T2, _} = timer:tc(?MODULE, test2, [Bin]),
>         {T3, _} = timer:tc(?MODULE, test4, [Bin]),
>         {T4, _} = timer:tc(?MODULE, test8, [Bin]),
>         {T5, _} = timer:tc(?MODULE, test16, [Bin]),
> 
>         io:format("T1 = ~p.~n", [T1]),
>         io:format("T2 = ~p.~n", [T2]),
>         io:format("T3 = ~p.~n", [T3]),
>         io:format("T4 = ~p.~n", [T4]),
>         io:format("T5 = ~p.~n", [T5]).
> 
> 




More information about the erlang-questions mailing list