Revert back to handling list of binaries (but differently)

Performance from last commit got worse not better :-(

Perhaps better handling all as lists, and then building a binary at the
end.
This commit is contained in:
martinsumner 2016-12-13 03:22:40 +00:00
parent 972a0ee0b9
commit aa2d19df1d

View file

@ -1268,75 +1268,63 @@ to_slotmap(HashTree, Index) ->
build_hashtree_binary(SlotMap, IndexLength) -> build_hashtree_binary(SlotMap, IndexLength) ->
build_hashtree_binary(SlotMap, IndexLength, 0, <<>>). build_hashtree_binary(SlotMap, IndexLength, 0, []).
build_hashtree_binary([], IdxLen, _SlotPos, Bin) -> build_hashtree_binary([], IdxLen, SlotPos, Bin) ->
case byte_size(Bin) div ?DWORD_SIZE of case SlotPos of
IdxLen -> IdxLen ->
Bin; lists:reverse(Bin);
N when N < IdxLen -> N when N < IdxLen ->
ZeroLen = (IdxLen - N) * 64, ZeroLen = (IdxLen - N) * 64,
<<Bin/binary, 0:ZeroLen>> lists:reverse([<<0:ZeroLen>>|Bin])
end; end;
build_hashtree_binary([{TopSlot, TopBin}|SlotMapTail], IdxLen, SlotPos, Bin) -> build_hashtree_binary([{TopSlot, TopBin}|SlotMapTail], IdxLen, SlotPos, Bin) ->
case TopSlot of case TopSlot of
SlotPos ->
UpdBin = <<Bin/binary, TopBin/binary>>,
build_hashtree_binary(SlotMapTail,
IdxLen,
SlotPos + 1,
UpdBin);
N when N > SlotPos -> N when N > SlotPos ->
Delta = N - SlotPos, D = N - SlotPos,
DeltaLen = Delta * 64, Bridge = lists:duplicate(D, <<0:64>>) ++ Bin,
UpdBin = <<Bin/binary, 0:DeltaLen, TopBin/binary>>, UpdBin = [<<TopBin/binary>>|Bridge],
build_hashtree_binary(SlotMapTail, build_hashtree_binary(SlotMapTail,
IdxLen, IdxLen,
SlotPos + Delta + 1, SlotPos + D + 1,
UpdBin); UpdBin);
N when N < SlotPos, SlotPos < IdxLen -> N when N =< SlotPos, SlotPos < IdxLen ->
UpdBin = <<Bin/binary, TopBin/binary>>, UpdBin = [<<TopBin/binary>>|Bin],
build_hashtree_binary(SlotMapTail, build_hashtree_binary(SlotMapTail,
IdxLen, IdxLen,
SlotPos + 1, SlotPos + 1,
UpdBin); UpdBin);
N when N < SlotPos, SlotPos >= IdxLen -> N when N < SlotPos, SlotPos == IdxLen ->
% Need to wrap round and put in the first empty slot from the % Need to wrap round and put in the first empty slot from the
% beginning % beginning
Pos = find_firstzero(Bin, 0) * 64, Pos = find_firstzero(Bin, length(Bin)),
UpdBin = {LHS, [<<0:64>>|RHS]} = lists:split(Pos - 1, Bin),
case Pos of UpdBin = lists:append(LHS, [TopBin|RHS]),
0 ->
<<0:64, Tail/binary>> = Bin,
<<TopBin/binary, Tail/binary>>;
_P ->
<<Head:Pos, 0:64, Tail/binary>> = Bin,
<<Head:Pos, TopBin/binary, Tail/binary>>
end,
build_hashtree_binary(SlotMapTail, build_hashtree_binary(SlotMapTail,
IdxLen, IdxLen,
SlotPos + 1, SlotPos,
UpdBin) UpdBin)
end. end.
find_firstzero(<<N:64/integer, TailBin/binary>>, Pos) -> % Search from the tail of the list to find the first zero
case N of find_firstzero(Bin, Pos) ->
0 -> case lists:nth(Pos, Bin) of
<<0:64>> ->
Pos; Pos;
_ -> _ ->
find_firstzero(TailBin, Pos + 1) find_firstzero(Bin, Pos - 1)
end. end.
write_hash_tables(Indexes, HashTree, CurrPos) -> write_hash_tables(Indexes, HashTree, CurrPos) ->
write_hash_tables(Indexes, HashTree, CurrPos, CurrPos, [], <<>>). write_hash_tables(Indexes, HashTree, CurrPos, CurrPos, [], []).
write_hash_tables([], _HashTree, _CurrPos, _BasePos, IndexList, HashTreeBin) -> write_hash_tables([], _HashTree, _CurrPos, _BasePos, IndexList, HT_BinList) ->
IL = lists:reverse(IndexList), IL = lists:reverse(IndexList),
{IL, HashTreeBin}; {IL, list_to_binary(HT_BinList)};
write_hash_tables([Index|Rest], HashTree, CurrPos, BasePos, write_hash_tables([Index|Rest], HashTree, CurrPos, BasePos,
IndexList, HashTreeBin) -> IndexList, HT_BinList) ->
case is_empty(HashTree, Index) of case is_empty(HashTree, Index) of
true -> true ->
write_hash_tables(Rest, write_hash_tables(Rest,
@ -1344,7 +1332,7 @@ write_hash_tables([Index|Rest], HashTree, CurrPos, BasePos,
CurrPos, CurrPos,
BasePos, BasePos,
[{Index, BasePos, 0}|IndexList], [{Index, BasePos, 0}|IndexList],
HashTreeBin); HT_BinList);
false -> false ->
SlotMap = to_slotmap(HashTree, Index), SlotMap = to_slotmap(HashTree, Index),
IndexLength = length(SlotMap) * 2, IndexLength = length(SlotMap) * 2,
@ -1354,7 +1342,7 @@ write_hash_tables([Index|Rest], HashTree, CurrPos, BasePos,
CurrPos + IndexLength * ?DWORD_SIZE, CurrPos + IndexLength * ?DWORD_SIZE,
BasePos, BasePos,
[{Index, CurrPos, IndexLength}|IndexList], [{Index, CurrPos, IndexLength}|IndexList],
<<HashTreeBin/binary, NewSlotBin/binary>>) HT_BinList ++ NewSlotBin)
end. end.
@ -1417,7 +1405,7 @@ build_hashtree_bunchedatend_binary_test() ->
{14, <<15:32, 500:32>>}, {14, <<15:32, 500:32>>},
{15, <<16:32, 600:32>>}, {15, <<16:32, 600:32>>},
{15, <<17:32, 700:32>>}], {15, <<17:32, 700:32>>}],
Bin = build_hashtree_binary(SlotMap, 16), Bin = list_to_binary(build_hashtree_binary(SlotMap, 16)),
ExpBinP1 = <<16:32, 600:32, 10:32, 0:32, 17:32, 700:32, 0:64>>, ExpBinP1 = <<16:32, 600:32, 10:32, 0:32, 17:32, 700:32, 0:64>>,
ExpBinP2 = <<11:32, 100:32, 0:192, 12:32, 200:32, 13:32, 300:32, 0:256>>, ExpBinP2 = <<11:32, 100:32, 0:192, 12:32, 200:32, 13:32, 300:32, 0:256>>,
ExpBinP3 = <<14:32, 400:32, 15:32, 500:32>>, ExpBinP3 = <<14:32, 400:32, 15:32, 500:32>>,
@ -1433,7 +1421,7 @@ build_hashtree_bunchedatstart_binary_test() ->
{6, <<15:32, 500:32>>}, {6, <<15:32, 500:32>>},
{7, <<16:32, 600:32>>}, {7, <<16:32, 600:32>>},
{8, <<17:32, 700:32>>}], {8, <<17:32, 700:32>>}],
Bin = build_hashtree_binary(SlotMap, 16), Bin = list_to_binary(build_hashtree_binary(SlotMap, 16)),
ExpBinP1 = <<0:64, 10:32, 0:32, 11:32, 100:32, 12:32, 200:32>>, ExpBinP1 = <<0:64, 10:32, 0:32, 11:32, 100:32, 12:32, 200:32>>,
ExpBinP2 = <<13:32, 300:32, 14:32, 400:32, 15:32, 500:32, 16:32, 600:32>>, ExpBinP2 = <<13:32, 300:32, 14:32, 400:32, 15:32, 500:32, 16:32, 600:32>>,
ExpBinP3 = <<17:32, 700:32, 0:448>>, ExpBinP3 = <<17:32, 700:32, 0:448>>,
@ -1443,8 +1431,15 @@ build_hashtree_bunchedatstart_binary_test() ->
?assertMatch(ExpBin, Bin). ?assertMatch(ExpBin, Bin).
find_firstzero_test() -> find_firstzero_test() ->
Bin = <<1:64/integer, 0:64/integer, 89:64/integer, 72:64/integer>>, Bin = [<<1:64/integer>>, <<0:64/integer>>,
?assertMatch(1, find_firstzero(Bin, 0)). <<89:64/integer>>, <<89:64/integer>>,
<<0:64/integer>>,
<<71:64/integer>>, <<72:64/integer>>],
?assertMatch(5, find_firstzero(Bin, length(Bin))),
{LHS, [<<0:64>>|RHS]} = lists:split(4, Bin),
?assertMatch([<<1:64/integer>>, <<0:64/integer>>,
<<89:64/integer>>, <<89:64/integer>>], LHS),
?assertMatch([<<71:64/integer>>, <<72:64/integer>>], RHS).
full_1_test() -> full_1_test() ->