[erlang-questions] Reverses Order of Bytes in Binary

Ivan Uemlianin ivan@REDACTED
Sat Jan 10 13:28:22 CET 2015


Testament to what a friendly language erlang is: the learner effortlessly arrives at the most fitting solution.

--
festina lente


> On 10 Jan 2015, at 12:06, Sergej Jurecko <sergej.jurecko@REDACTED> wrote:
> 
> Async version so results are less skewed by GC. 
> With a larger bin it is more clear what the best solution is:
> 
> bin_reverse:reverse_test(crypto:rand_bytes(100000)).
> "list"=15515
> "tail_pos"=24061
> "list_to_bin"=28627
> "body_pos"=4781891
> 
> -module(bin_reverse).
> -export([reverse_test/1]).
> 
> 
> reverse_test(Bin) ->
>     [
>         async("body_pos",fun reverse_body_pos/1,Bin),
>         async("tail_pos",fun reverse_tail_pos/1,Bin),
>         async("list",fun reverse_list/1,Bin),
>         async("list_to_bin",fun reverse_list_to_bin/1,Bin)
>     ].
> 
> async(Name,Fun,Bin) ->
>     spawn(fun() ->
>         {T,_} = timer:tc(Fun,[Bin]),
>         io:format("~p=~p~n",[Name,T])
>     end).
> 
> 
> reverse_tail_pos(Bin) ->
>     reverse1(Bin, byte_size(Bin), <<>>).
> 
> reverse1(_, 0, Acc) -> Acc;
> reverse1(Bin, Pos, Acc) ->
>     reverse1(Bin, Pos - 1, <<Acc/binary, (binary:at(Bin, Pos - 1))>>).
> 
> 
> 
> reverse_body_pos(Bin) ->
>     reverse2(Bin, byte_size(Bin)).
> 
> reverse2(_, 0) -> <<>>;
> reverse2(Bin, Pos) ->
>     <<(binary:at(Bin, Pos - 1)), (reverse2(Bin, Pos - 1))/binary >>.
> 
> 
> 
> reverse_list(Bin) ->
>     list_to_binary(lists:reverse(binary_to_list(Bin))).
> 
> 
> 
> reverse_list_to_bin(Bin) ->
>     reverse3(Bin, []).
> 
> reverse3(<<>>, Acc) -> list_to_binary(Acc);
> reverse3(<<C,Bin/binary>>, Acc) -> reverse3(Bin, [C|Acc]).
> 
> 
>> On 10 Jan 2015, at 12:46, Сергей Прохоров <seriy.pr@REDACTED> wrote:
>> 
>> Ok, looks like topicstarter's solution is the fastest one:
>> 
>> =======================
>> -module(bin_reverse).
>> -export([reverse_test/1]).
>> 
>> 
>> reverse_test(Bin) ->
>>     [
>>      {"body_pos", timer:tc(fun reverse_body_pos/1, [Bin])},
>>      {"tail_pos", timer:tc(fun reverse_tail_pos/1, [Bin])},
>>      {"list", timer:tc(fun reverse_list/1, [Bin])},
>>      {"list_to_bin", timer:tc(fun reverse_list_to_bin/1, [Bin])}
>>     ].
>> 
>> 
>> 
>> reverse_tail_pos(Bin) ->
>>     reverse1(Bin, byte_size(Bin), <<>>).
>> 
>> reverse1(_, 0, Acc) -> Acc;
>> reverse1(Bin, Pos, Acc) ->
>>     reverse1(Bin, Pos - 1, <<Acc/binary, (binary:at(Bin, Pos - 1))>>).
>> 
>> 
>> 
>> reverse_body_pos(Bin) ->
>>     reverse2(Bin, byte_size(Bin)).
>> 
>> reverse2(_, 0) -> <<>>;
>> reverse2(Bin, Pos) ->
>>     <<(binary:at(Bin, Pos - 1)), (reverse2(Bin, Pos - 1))/binary >>.
>> 
>> 
>> 
>> reverse_list(Bin) ->
>>     list_to_binary(lists:reverse(binary_to_list(Bin))).
>> 
>> 
>> 
>> reverse_list_to_bin(Bin) ->
>>     reverse3(Bin, []).
>> 
>> reverse3(<<>>, Acc) -> list_to_binary(Acc);
>> reverse3(<<C,Bin/binary>>, Acc) -> reverse3(Bin, [C|Acc]).
>> 
>> =======================
>> 
>> 24> bin_reverse:reverse_test(crypto:rand_bytes(100)).
>> [{"body_pos",
>>   {32,
>>    <<247,128,13,6,1,53,110,148,74,210,196,126,234,115,180,
>>      85,33,206,130,164,3,242,174,157,...>>}},
>>  {"tail_pos",
>>   {14,
>>    <<247,128,13,6,1,53,110,148,74,210,196,126,234,115,180,
>>      85,33,206,130,164,3,242,174,...>>}},
>>  {"list",
>>   {3,
>>    <<247,128,13,6,1,53,110,148,74,210,196,126,234,115,180,
>>      85,33,206,130,164,3,242,...>>}},
>>  {"list_to_bin",
>>   {13,
>>    <<247,128,13,6,1,53,110,148,74,210,196,126,234,115,180,
>>      85,33,206,130,164,3,...>>}}]
>> 
>> 2015-01-10 14:30 GMT+03:00 Ivan Uemlianin <ivan@REDACTED>:
>>> Remember lists:reverse/1 is implemented in C & does some non-erlangy things (IIRC) so should be jolly fast & efficient.  Unless binary_to_list/1 is v bad the OP's version is the best so far (imho).
>>> 
>>> Best wishes
>>> 
>>> Ivan
>>> 
>>> 
>>> --
>>> festina lente
>>> 
>>> 
>>> > On 10 Jan 2015, at 11:24, Сергей Прохоров <seriy.pr@REDACTED> wrote:
>>> >
>>> > Probably this one will be more effective
>>> >
>>> > reverse(Bin) ->
>>> >     reverse(Bin, byte_size(Bin)).
>>> >
>>> > reverse(_, 0) -> <<>>;
>>> > reverse(Bin, Pos) ->
>>> >     <<(binary:at(Bin, Pos - 1)), (reverse(Bin, Pos - 1))/binary >>.
>>> > _______________________________________________
>>> > 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/20150110/8ad96d2b/attachment.htm>


More information about the erlang-questions mailing list