[erlang-questions] Reverses Order of Bytes in Binary
Vincent de Phily
vincent.dephily@REDACTED
Mon Jan 12 12:10:39 CET 2015
On Friday 09 January 2015 18:18:26 Max Lapshin wrote:
> Ah, really. I should be ashamed.
>
> reverse(Bin) ->
> reverse(Bin, []).
>
> reverse(<<>>, Acc) -> list_to_binary(Acc);
> reverse(<<C,Bin/binary>>, Acc) -> reverse(Bin, [C|Acc]).
I microbenched various implementations with small and large binaries trying to
get rid of the intermediate list representation and was really surprised by
the results :
l(B) -> list_to_binary(lists:reverse(binary_to_list(B))).
b(Bin) -> b(Bin, []).
b(<<>>, Acc) -> list_to_binary(Acc);
b(<<C,Bin/binary>>, Acc) -> b(Bin, [C|Acc]).
b1(Bin) -> b1(Bin, <<>>).
b1(<<>>, Acc) -> Acc;
b1(<<C,Bin/binary>>, Acc) -> b1(Bin, <<C,Acc/binary>>).
b2(B) -> b2(B,byte_size(B)-1,<<>>).
b2(B,0,Acc) -> <<Acc/binary,(binary:at(B,0))>>;
b2(B,N,Acc) -> b2(B,N-1,<<Acc/binary,(binary:at(B,N))>>).
I consistently get l/1 fastest:
l 10225
b 14247
b1 339329
b2 50249
I'm surprised that the list/binary conversions are that cheap (compared to
directly parsing/building the binary) because of all the small memory
allocations they need to do.
Is there some native optimisation they use that plain erlang can't use ?
Typically, does list_to_binary/1 construct the binary in a more efficient way
than is possible from plain erlang ? When decontructing l/1 into its 3 steps I
find that binary_to_list takes just slightly longer than reverse, and
list_to_binary takes a good bit less.
For what it's worth, binary:reverse/1 could probably be much faster if
implemented as a bif. I wonder if it'd be worth it to have some kind of
binary:preallocate/2 function.
--
Vincent de Phily
More information about the erlang-questions
mailing list