[erlang-questions] Real basic binary manipulation question

Sergey S <>
Sun Jan 18 16:25:05 CET 2009


Hello.

Thanks for this discussion (which was very usefull) and especially for
the trick with binary used as an accumulator (decompress2).

Here is another implementation (just to have as many variants as
possible :) using a deep list as an accumulator:

decompress3(Bin) when is_binary(Bin) ->
    decompress3(Bin, []).

decompress3(<<0, Count, Tail/binary>>, Acc) ->
    decompress3(Tail, [Acc, <<0:(Count * 8)>>]);
decompress3(<<Head, Tail/binary>>, Acc) ->
    decompress3(Tail, [Acc, Head]);
decompress3(<<>>, Acc) ->
    list_to_binary(Acc).

It's slower than decompress2 but a bit faster (and more memory
consuming) than decompress1:

Eshell V5.6.5  (abort with ^G)
1> c(zrle), zrle:bm().
decompress1: 1520 (1525)
decompress2: 1110 (1104)
decompress3: 1470 (1477)
ok
2> c(zrle, [native]), zrle:bm().
decompress1: 1170 (1193)
decompress2: 720 (715)
decompress3: 1040 (1047)
ok

% -HERE-IS-THE-SOURCES-----------------------------

-module(zrle).
-compile(export_all).

bm() ->
    bm(<<1,0,3,0,4,0,10,0,15,0,150>>, 500000).
bm(Bin, N) ->

    statistics(runtime),
    statistics(wall_clock),

    repeat(fun() -> decompress(Bin) end, N),
    {_, R1} = statistics(runtime),
    {_, W1} = statistics(wall_clock),

    repeat(fun() -> decompress2(Bin) end, N),
    {_, R2} = statistics(runtime),
    {_, W2} = statistics(wall_clock),

    repeat(fun() -> decompress3(Bin) end, N),
    {_, R3} = statistics(runtime),
    {_, W3} = statistics(wall_clock),

    io:format("decompress1: ~p (~p)~n", [R1, W1]),
    io:format("decompress2: ~p (~p)~n", [R2, W2]),
    io:format("decompress3: ~p (~p)~n", [R3, W3]).

repeat(_, 0) ->
    ok;
repeat(Fun, N) ->
    Fun(),
    repeat(Fun, N - 1).

decompress(Bin) when is_binary(Bin) ->
    decompress(Bin, []).

decompress(<<0, Count, Tail/binary>>, Acc) ->
    decompress(Tail, [<<0:(Count * 8)>> | Acc]);
decompress(<<Head, Tail/binary>>, Acc) ->
    decompress(Tail, [Head | Acc]);
decompress(<<>>, Acc) ->
    list_to_binary(lists:reverse(Acc)).

decompress2(Bin) when is_binary(Bin) ->
    decompress2(Bin, <<>>).

decompress2(<<0, Count, Tail/binary>>, Acc) ->
    decompress2(Tail, <<Acc/binary, 0:(Count * 8)>>);
decompress2(<<Head, Tail/binary>>, Acc) ->
    decompress2(Tail, <<Acc/binary, Head>>);
decompress2(<<>>, Acc) ->
    Acc.

decompress3(Bin) when is_binary(Bin) ->
    decompress3(Bin, []).

decompress3(<<0, Count, Tail/binary>>, Acc) ->
    decompress3(Tail, [Acc, <<0:(Count * 8)>>]);
decompress3(<<Head, Tail/binary>>, Acc) ->
    decompress3(Tail, [Acc, Head]);
decompress3(<<>>, Acc) ->
    list_to_binary(Acc).

--
Sergey



More information about the erlang-questions mailing list