Add skiplist into leveled_tree
Getting ready to remove seperate skiplist module. Need to add the skiplist support in leveled_tree for relative testing.
This commit is contained in:
parent
f031558b28
commit
0fa22ab4b3
1 changed files with 79 additions and 9 deletions
|
@ -29,6 +29,7 @@
|
|||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
-define(SKIP_WIDTH, 16).
|
||||
-define(WIDTH_MAP, [{64, 4}, {512, 8}, {4096, 16}, {infinity, 32}]).
|
||||
|
||||
|
||||
%%%============================================================================
|
||||
|
@ -38,10 +39,10 @@
|
|||
from_orderedset(Table, Type) ->
|
||||
from_orderedlist(ets:tab2list(Table), Type, ?SKIP_WIDTH).
|
||||
|
||||
|
||||
from_orderedset(Table, Type, SkipWidth) ->
|
||||
from_orderedlist(ets:tab2list(Table), Type, SkipWidth).
|
||||
|
||||
|
||||
from_orderedlist(OrderedList, Type) ->
|
||||
from_orderedlist(OrderedList, Type, ?SKIP_WIDTH).
|
||||
|
||||
|
@ -50,7 +51,19 @@ from_orderedlist(OrderedList, tree, SkipWidth) ->
|
|||
{tree, L, tree_fromorderedlist(OrderedList, [], L, SkipWidth)};
|
||||
from_orderedlist(OrderedList, idxt, SkipWidth) ->
|
||||
L = length(OrderedList),
|
||||
{idxt, L, idxt_fromorderedlist(OrderedList, {[], [], 1}, L, SkipWidth)}.
|
||||
{idxt, L, idxt_fromorderedlist(OrderedList, {[], [], 1}, L, SkipWidth)};
|
||||
from_orderedlist(OrderedList, skpl, _SkipWidth) ->
|
||||
L = length(OrderedList),
|
||||
SkipWidth =
|
||||
% Autosize the skip width
|
||||
case L of
|
||||
L when L > 4096 -> 32;
|
||||
L when L > 512 -> 16;
|
||||
L when L > 64 -> 8;
|
||||
_ -> 4
|
||||
end,
|
||||
{skpl, L, skpl_fromorderedlist(OrderedList, L, SkipWidth, 2)}.
|
||||
|
||||
|
||||
match(Key, {tree, _L, Tree}) ->
|
||||
Iter = tree_iterator_from(Key, Tree),
|
||||
|
@ -67,7 +80,20 @@ match(Key, {idxt, _L, {TLI, IDX}}) ->
|
|||
none;
|
||||
{_NK, ListID, _Iter} ->
|
||||
lookup_match(Key, element(ListID, TLI))
|
||||
end.
|
||||
end;
|
||||
match(Key, {skpl, _L, SkipList}) ->
|
||||
FoldFun =
|
||||
fun({Mark, SL}, Acc) ->
|
||||
case {Acc, Mark} of
|
||||
{[], Mark} when Mark >= Key ->
|
||||
SL;
|
||||
_ ->
|
||||
Acc
|
||||
end
|
||||
end,
|
||||
SL1 = lists:foldl(FoldFun, [], SkipList),
|
||||
SL0 = lists:foldl(FoldFun, [], SL1),
|
||||
lookup_match(Key, SL0).
|
||||
|
||||
search(Key, {tree, _L, Tree}, StartKeyFun) ->
|
||||
Iter = tree_iterator_from(Key, Tree),
|
||||
|
@ -96,6 +122,25 @@ search(Key, {idxt, _L, {TLI, IDX}}, StartKeyFun) ->
|
|||
false ->
|
||||
{K, V}
|
||||
end
|
||||
end;
|
||||
search(Key, {skpl, _L, SkipList}, StartKeyFun) ->
|
||||
FoldFun =
|
||||
fun({Mark, SL}, Acc) ->
|
||||
case {Acc, Mark} of
|
||||
{[], Mark} when Mark >= Key ->
|
||||
SL;
|
||||
_ ->
|
||||
Acc
|
||||
end
|
||||
end,
|
||||
SL1 = lists:foldl(FoldFun, [], SkipList),
|
||||
SL0 = lists:foldl(FoldFun, [], SL1),
|
||||
{K, V} = lookup_best(Key, SL0),
|
||||
case K < StartKeyFun(V) of
|
||||
true ->
|
||||
none;
|
||||
false ->
|
||||
{K, V}
|
||||
end.
|
||||
|
||||
|
||||
|
@ -111,6 +156,7 @@ match_range(StartRange, EndRange, {tree, _L, Tree}, EndRangeFun) ->
|
|||
match_range(StartRange, EndRange, {idxt, _L, Tree}, EndRangeFun) ->
|
||||
idxtlookup_range_start(StartRange, EndRange, Tree, EndRangeFun).
|
||||
|
||||
|
||||
search_range(StartRange, EndRange, Tree, StartKeyFun) ->
|
||||
EndRangeFun =
|
||||
fun(ER, _FirstRHSKey, FirstRHSValue) ->
|
||||
|
@ -124,6 +170,7 @@ search_range(StartRange, EndRange, Tree, StartKeyFun) ->
|
|||
idxtlookup_range_start(StartRange, EndRange, T, EndRangeFun)
|
||||
end.
|
||||
|
||||
|
||||
to_list({tree, _L, Tree}) ->
|
||||
FoldFun =
|
||||
fun({_MK, SL}, Acc) ->
|
||||
|
@ -133,6 +180,7 @@ to_list({tree, _L, Tree}) ->
|
|||
to_list({idxt, _L, {TLI, _IDX}}) ->
|
||||
lists:append(tuple_to_list(TLI)).
|
||||
|
||||
|
||||
tsize({_Type, L, _Tree}) ->
|
||||
L.
|
||||
|
||||
|
@ -168,6 +216,22 @@ idxt_fromorderedlist(OrdList, {TmpListElements, TmpListIdx, C}, L, SkipWidth) ->
|
|||
L - SubLL,
|
||||
SkipWidth).
|
||||
|
||||
skpl_fromorderedlist(SkipList, _L, _SkipWidth, 0) ->
|
||||
SkipList;
|
||||
skpl_fromorderedlist(SkipList, L, SkipWidth, Height) ->
|
||||
SkipList0 = roll_list(SkipList, L, [], SkipWidth),
|
||||
skpl_fromorderedlist(SkipList0, length(SkipList0), SkipWidth, Height - 1).
|
||||
|
||||
roll_list([], 0, SkipList, _SkipWidth) ->
|
||||
lists:reverse(SkipList);
|
||||
roll_list(KVList, L, SkipList, SkipWidth) ->
|
||||
SubLL = min(SkipWidth, L),
|
||||
{Head, Tail} = lists:split(SubLL, KVList),
|
||||
{LastK, _LastV} = lists:last(Head),
|
||||
roll_list(Tail, L - SubLL, [{LastK, Head}|SkipList], SkipWidth).
|
||||
|
||||
|
||||
|
||||
lookup_match(_Key, []) ->
|
||||
none;
|
||||
lookup_match(Key, [{EK, _EV}|_Tail]) when EK > Key ->
|
||||
|
@ -391,16 +455,22 @@ search_test_by_type(Type) ->
|
|||
|
||||
|
||||
tree_timing_test() ->
|
||||
tree_test_by_(8, tree),
|
||||
tree_test_by_(16, tree).
|
||||
tree_test_by_(16, tree, 4000),
|
||||
tree_test_by_(8, tree, 1000),
|
||||
tree_test_by_(4, tree, 128).
|
||||
|
||||
idxt_timing_test() ->
|
||||
tree_test_by_(16, idxt),
|
||||
tree_test_by_(8, idxt).
|
||||
tree_test_by_(16, idxt, 4000),
|
||||
tree_test_by_(8, idxt, 1000),
|
||||
tree_test_by_(4, idxt, 128).
|
||||
|
||||
tree_test_by_(Width, Type) ->
|
||||
skpl_timing_test() ->
|
||||
tree_test_by_(auto, skpl, 4000),
|
||||
tree_test_by_(auto, skpl, 1000),
|
||||
tree_test_by_(auto, skpl, 128).
|
||||
|
||||
tree_test_by_(Width, Type, N) ->
|
||||
io:format(user, "~nTree test for type and width: ~w ~w~n", [Type, Width]),
|
||||
N = 4000,
|
||||
KL = lists:ukeysort(1, generate_randomkeys(1, N, 1, N div 5)),
|
||||
|
||||
OS = ets:new(test, [ordered_set, private]),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue