Change so that type of cache is parameterised

The Tree doesn't seem to be better than the skiplist.  Get ready to make
this switchable
This commit is contained in:
martinsumner 2017-01-21 11:38:26 +00:00
parent 4846272393
commit ed96d0ca7a
5 changed files with 48 additions and 30 deletions

View file

@ -15,6 +15,8 @@
%% Inker key type used for tombstones %% Inker key type used for tombstones
-define(INKT_TOMB, tomb). -define(INKT_TOMB, tomb).
-define(CACHE_TYPE, tree).
-record(sft_options, -record(sft_options,
{wait = true :: boolean(), {wait = true :: boolean(),
expire_tombstones = false :: boolean(), expire_tombstones = false :: boolean(),

View file

@ -154,7 +154,7 @@
-define(LONG_RUNNING, 80000). -define(LONG_RUNNING, 80000).
-record(ledger_cache, {mem :: ets:tab(), -record(ledger_cache, {mem :: ets:tab(),
loader = leveled_tree:empty() :: tuple(), loader = leveled_tree:empty(?CACHE_TYPE) :: tuple(),
load_queue = [] :: list(), load_queue = [] :: list(),
index = leveled_pmem:new_index(), % array index = leveled_pmem:new_index(), % array
min_sqn = infinity :: integer()|infinity, min_sqn = infinity :: integer()|infinity,
@ -478,7 +478,7 @@ push_ledgercache(Penciller, Cache) ->
loadqueue_ledgercache(Cache) -> loadqueue_ledgercache(Cache) ->
SL = lists:ukeysort(1, Cache#ledger_cache.load_queue), SL = lists:ukeysort(1, Cache#ledger_cache.load_queue),
T = leveled_tree:from_orderedlist(SL), T = leveled_tree:from_orderedlist(SL, ?CACHE_TYPE),
Cache#ledger_cache{load_queue = [], loader = T}. Cache#ledger_cache{load_queue = [], loader = T}.
%%%============================================================================ %%%============================================================================
@ -726,7 +726,8 @@ snapshot_store(State, SnapType) ->
readycache_forsnapshot(LedgerCache) -> readycache_forsnapshot(LedgerCache) ->
% Need to convert the Ledger Cache away from using the ETS table % Need to convert the Ledger Cache away from using the ETS table
Tree = leveled_tree:from_orderedset(LedgerCache#ledger_cache.mem), Tree = leveled_tree:from_orderedset(LedgerCache#ledger_cache.mem,
?CACHE_TYPE),
Idx = LedgerCache#ledger_cache.index, Idx = LedgerCache#ledger_cache.index,
MinSQN = LedgerCache#ledger_cache.min_sqn, MinSQN = LedgerCache#ledger_cache.min_sqn,
MaxSQN = LedgerCache#ledger_cache.max_sqn, MaxSQN = LedgerCache#ledger_cache.max_sqn,
@ -982,7 +983,7 @@ maybepush_ledgercache(MaxCacheSize, Cache, Penciller) ->
TimeToPush = maybe_withjitter(CacheSize, MaxCacheSize), TimeToPush = maybe_withjitter(CacheSize, MaxCacheSize),
if if
TimeToPush -> TimeToPush ->
CacheToLoad = {leveled_tree:from_orderedset(Tab), CacheToLoad = {leveled_tree:from_orderedset(Tab, ?CACHE_TYPE),
Cache#ledger_cache.index, Cache#ledger_cache.index,
Cache#ledger_cache.min_sqn, Cache#ledger_cache.min_sqn,
Cache#ledger_cache.max_sqn}, Cache#ledger_cache.max_sqn},

View file

@ -404,7 +404,7 @@ handle_call({fetch_keys, StartKey, EndKey, AccFun, InitAcc, MaxKeys},
leveled_pmem:merge_trees(StartKey, leveled_pmem:merge_trees(StartKey,
EndKey, EndKey,
State#state.levelzero_cache, State#state.levelzero_cache,
leveled_tree:empty()); leveled_tree:empty(?CACHE_TYPE));
List -> List ->
List List
end, end,
@ -1084,7 +1084,7 @@ maybe_pause_push(PCL, KL) ->
{T0, I0, infinity, 0}, {T0, I0, infinity, 0},
KL), KL),
SL = element(1, T1), SL = element(1, T1),
Tree = leveled_tree:from_orderedlist(lists:ukeysort(1, SL)), Tree = leveled_tree:from_orderedlist(lists:ukeysort(1, SL), ?CACHE_TYPE),
T2 = setelement(1, T1, Tree), T2 = setelement(1, T1, Tree),
case pcl_pushmem(PCL, T2) of case pcl_pushmem(PCL, T2) of
returned -> returned ->
@ -1330,7 +1330,7 @@ foldwithimm_simple_test() ->
KL1A = [{{o, "Bucket1", "Key6", null}, {7, {active, infinity}, 0, null}}, KL1A = [{{o, "Bucket1", "Key6", null}, {7, {active, infinity}, 0, null}},
{{o, "Bucket1", "Key1", null}, {8, {active, infinity}, 0, null}}, {{o, "Bucket1", "Key1", null}, {8, {active, infinity}, 0, null}},
{{o, "Bucket1", "Key8", null}, {9, {active, infinity}, 0, null}}], {{o, "Bucket1", "Key8", null}, {9, {active, infinity}, 0, null}}],
IMM2 = leveled_tree:from_orderedlist(lists:ukeysort(1, KL1A)), IMM2 = leveled_tree:from_orderedlist(lists:ukeysort(1, KL1A), ?CACHE_TYPE),
IMMiter = leveled_tree:match_range({o, "Bucket1", "Key1", null}, IMMiter = leveled_tree:match_range({o, "Bucket1", "Key1", null},
{o, null, null, null}, {o, null, null, null},
IMM2), IMM2),
@ -1356,7 +1356,7 @@ foldwithimm_simple_test() ->
{{o, "Bucket1", "Key5", null}, 2}], AccA), {{o, "Bucket1", "Key5", null}, 2}], AccA),
KL1B = [{{o, "Bucket1", "Key4", null}, {10, {active, infinity}, 0, null}}|KL1A], KL1B = [{{o, "Bucket1", "Key4", null}, {10, {active, infinity}, 0, null}}|KL1A],
IMM3 = leveled_tree:from_orderedlist(lists:ukeysort(1, KL1B)), IMM3 = leveled_tree:from_orderedlist(lists:ukeysort(1, KL1B), ?CACHE_TYPE),
IMMiterB = leveled_tree:match_range({o, "Bucket1", "Key1", null}, IMMiterB = leveled_tree:match_range({o, "Bucket1", "Key1", null},
{o, null, null, null}, {o, null, null, null},
IMM3), IMM3),
@ -1374,7 +1374,7 @@ create_file_test() ->
Filename = "../test/new_file.sst", Filename = "../test/new_file.sst",
ok = file:write_file(Filename, term_to_binary("hello")), ok = file:write_file(Filename, term_to_binary("hello")),
KVL = lists:usort(generate_randomkeys(10000)), KVL = lists:usort(generate_randomkeys(10000)),
Tree = leveled_tree:from_orderedlist(KVL), Tree = leveled_tree:from_orderedlist(KVL, ?CACHE_TYPE),
FetchFun = fun(Slot) -> lists:nth(Slot, [Tree]) end, FetchFun = fun(Slot) -> lists:nth(Slot, [Tree]) end,
{ok, {ok,
SP, SP,

View file

@ -188,7 +188,7 @@ generate_randomkeys(Seqn, Count, BucketRangeLow, BucketRangeHigh) ->
[], [],
BucketRangeLow, BucketRangeLow,
BucketRangeHigh), BucketRangeHigh),
leveled_tree:from_orderedlist(lists:ukeysort(1, KVL)). leveled_tree:from_orderedlist(lists:ukeysort(1, KVL), ?CACHE_TYPE).
generate_randomkeys(_Seqn, 0, Acc, _BucketLow, _BucketHigh) -> generate_randomkeys(_Seqn, 0, Acc, _BucketLow, _BucketHigh) ->
Acc; Acc;
@ -277,13 +277,13 @@ compare_method_test() ->
end, end,
[], [],
DumpList), DumpList),
Tree = leveled_tree:from_orderedlist(lists:ukeysort(1, Q0)), Tree = leveled_tree:from_orderedlist(lists:ukeysort(1, Q0), ?CACHE_TYPE),
Sz0 = leveled_tree:tsize(Tree), Sz0 = leveled_tree:tsize(Tree),
io:format("Crude method took ~w microseconds resulting in tree of " ++ io:format("Crude method took ~w microseconds resulting in tree of " ++
"size ~w~n", "size ~w~n",
[timer:now_diff(os:timestamp(), SWa), Sz0]), [timer:now_diff(os:timestamp(), SWa), Sz0]),
SWb = os:timestamp(), SWb = os:timestamp(),
Q1 = merge_trees(StartKey, EndKey, TreeList, leveled_tree:empty()), Q1 = merge_trees(StartKey, EndKey, TreeList, leveled_tree:empty(?CACHE_TYPE)),
Sz1 = length(Q1), Sz1 = length(Q1),
io:format("Merge method took ~w microseconds resulting in tree of " ++ io:format("Merge method took ~w microseconds resulting in tree of " ++
"size ~w~n", "size ~w~n",
@ -300,7 +300,7 @@ with_index_test() ->
fun(_X, {{LedgerSQN, L0Size, L0TreeList}, L0Idx, SrcList}) -> fun(_X, {{LedgerSQN, L0Size, L0TreeList}, L0Idx, SrcList}) ->
LM1 = generate_randomkeys_aslist(LedgerSQN + 1, 2000, 1, 500), LM1 = generate_randomkeys_aslist(LedgerSQN + 1, 2000, 1, 500),
LM1Array = lists:foldl(IndexPrepareFun, new_index(), LM1), LM1Array = lists:foldl(IndexPrepareFun, new_index(), LM1),
LM1SL = leveled_tree:from_orderedlist(lists:ukeysort(1, LM1)), LM1SL = leveled_tree:from_orderedlist(lists:ukeysort(1, LM1), ?CACHE_TYPE),
UpdL0Index = add_to_index(LM1Array, L0Idx, length(L0TreeList) + 1), UpdL0Index = add_to_index(LM1Array, L0Idx, length(L0TreeList) + 1),
R = add_to_cache(L0Size, R = add_to_cache(L0Size,
{LM1SL, LedgerSQN + 1, LedgerSQN + 2000}, {LM1SL, LedgerSQN + 1, LedgerSQN + 2000},

View file

@ -13,15 +13,17 @@
-include("include/leveled.hrl"). -include("include/leveled.hrl").
-export([ -export([
from_orderedlist/1, from_orderedlist/2,
from_orderedset/1, from_orderedset/2,
from_orderedlist/3,
from_orderedset/3,
to_list/1, to_list/1,
match_range/3, match_range/3,
search_range/4, search_range/4,
match/2, match/2,
search/3, search/3,
tsize/1, tsize/1,
empty/0 empty/1
]). ]).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
@ -33,12 +35,18 @@
%%% API %%% API
%%%============================================================================ %%%============================================================================
from_orderedlist(OrderedList) -> from_orderedset(Table, tree) ->
L = length(OrderedList), from_orderedlist(ets:tab2list(Table), tree, ?SKIP_WIDTH).
{tree, L, from_orderedlist(OrderedList, [], L)}.
from_orderedset(Table) -> from_orderedset(Table, tree, SkipWidth) ->
from_orderedlist(ets:tab2list(Table)). from_orderedlist(ets:tab2list(Table), tree, SkipWidth).
from_orderedlist(OrderedList, tree) ->
from_orderedlist(OrderedList, tree, ?SKIP_WIDTH).
from_orderedlist(OrderedList, tree, SkipWidth) ->
L = length(OrderedList),
{tree, L, from_orderedlist(OrderedList, [], L, SkipWidth)}.
match(Key, {tree, _L, Tree}) -> match(Key, {tree, _L, Tree}) ->
Iter = tree_iterator_from(Key, Tree), Iter = tree_iterator_from(Key, Tree),
@ -90,7 +98,7 @@ to_list({tree, _L, Tree}) ->
tsize({tree, L, _Tree}) -> tsize({tree, L, _Tree}) ->
L. L.
empty() -> empty(tree) ->
{tree, 0, empty_tree()}. {tree, 0, empty_tree()}.
%%%============================================================================ %%%============================================================================
@ -98,13 +106,13 @@ empty() ->
%%%============================================================================ %%%============================================================================
from_orderedlist([], TmpList, _L) -> from_orderedlist([], TmpList, _L, _SkipWidth) ->
gb_trees:from_orddict(lists:reverse(TmpList)); gb_trees:from_orddict(lists:reverse(TmpList));
from_orderedlist(OrdList, TmpList, L) -> from_orderedlist(OrdList, TmpList, L, SkipWidth) ->
SubLL = min(?SKIP_WIDTH, L), SubLL = min(SkipWidth, L),
{Head, Tail} = lists:split(SubLL, OrdList), {Head, Tail} = lists:split(SubLL, OrdList),
{LastK, _LastV} = lists:last(Head), {LastK, _LastV} = lists:last(Head),
from_orderedlist(Tail, [{LastK, Head}|TmpList], L - SubLL). from_orderedlist(Tail, [{LastK, Head}|TmpList], L - SubLL, SkipWidth).
lookup_match(_Key, []) -> lookup_match(_Key, []) ->
none; none;
@ -256,7 +264,7 @@ tree_search_test() ->
{N * 4, N * 4 - 2} {N * 4, N * 4 - 2}
end, end,
KL = lists:map(MapFun, lists:seq(1, 50)), KL = lists:map(MapFun, lists:seq(1, 50)),
T = from_orderedlist(KL), T = from_orderedlist(KL, tree),
StartKeyFun = fun(V) -> V end, StartKeyFun = fun(V) -> V end,
@ -274,22 +282,29 @@ tree_search_test() ->
io:format(user, "10 range tests in ~w microseconds~n", io:format(user, "10 range tests in ~w microseconds~n",
[timer:now_diff(os:timestamp(), SW)]). [timer:now_diff(os:timestamp(), SW)]).
tree_test() -> tree_test() ->
tree_test_by_width(8),
tree_test_by_width(16),
tree_test_by_width(32),
tree_test_by_width(4).
tree_test_by_width(Width) ->
io:format(user, "~nTree test for width: ~w~n", [Width]),
N = 4000, N = 4000,
KL = lists:ukeysort(1, generate_randomkeys(1, N, 1, N div 5)), KL = lists:ukeysort(1, generate_randomkeys(1, N, 1, N div 5)),
OS = ets:new(test, [ordered_set, private]), OS = ets:new(test, [ordered_set, private]),
ets:insert(OS, KL), ets:insert(OS, KL),
SWaETS = os:timestamp(), SWaETS = os:timestamp(),
Tree0 = from_orderedset(OS), Tree0 = from_orderedset(OS, tree, Width),
io:format(user, "Generating tree from ETS in ~w microseconds" ++ io:format(user, "Generating tree from ETS in ~w microseconds" ++
" of size ~w~n", " of size ~w~n",
[timer:now_diff(os:timestamp(), SWaETS), [timer:now_diff(os:timestamp(), SWaETS),
tsize(Tree0)]), tsize(Tree0)]),
SWaGSL = os:timestamp(), SWaGSL = os:timestamp(),
Tree1 = from_orderedlist(KL), Tree1 = from_orderedlist(KL, tree, Width),
io:format(user, "Generating tree from orddict in ~w microseconds" ++ io:format(user, "Generating tree from orddict in ~w microseconds" ++
" of size ~w~n", " of size ~w~n",
[timer:now_diff(os:timestamp(), SWaGSL), [timer:now_diff(os:timestamp(), SWaGSL),