242 lines
7.3 KiB
Erlang
242 lines
7.3 KiB
Erlang
![]() |
-module(lookup_test).
|
||
|
|
||
|
-export([go_dict/1, go_ets/1, go_gbtree/1,
|
||
|
go_arrayofdict/1, go_arrayofgbtree/1, go_arrayofdict_withcache/1]).
|
||
|
|
||
|
-define(CACHE_SIZE, 512).
|
||
|
|
||
|
hash(Key) ->
|
||
|
H = 5381,
|
||
|
hash1(H,Key) band 16#FFFFFFFF.
|
||
|
|
||
|
hash1(H,[]) ->H;
|
||
|
hash1(H,[B|Rest]) ->
|
||
|
H1 = H * 33,
|
||
|
H2 = H1 bxor B,
|
||
|
hash1(H2,Rest).
|
||
|
|
||
|
% Get the least significant 8 bits from the hash.
|
||
|
hash_to_index(Hash) ->
|
||
|
Hash band 255.
|
||
|
|
||
|
|
||
|
%%
|
||
|
%% Timings (microseconds):
|
||
|
%%
|
||
|
%% go_dict(200000) : 1569894
|
||
|
%% go_dict(1000000) : 17191365
|
||
|
%% go_dict(5000000) : forever
|
||
|
|
||
|
go_dict(N) ->
|
||
|
go_dict(dict:new(), N, N).
|
||
|
|
||
|
go_dict(_, 0, _) ->
|
||
|
{erlang:memory(), statistics(garbage_collection)};
|
||
|
go_dict(D, N, M) ->
|
||
|
% Lookup a random key - which may not be present
|
||
|
LookupKey = lists:concat(["key-", random:uniform(M)]),
|
||
|
LookupHash = hash(LookupKey),
|
||
|
dict:find(LookupHash, D),
|
||
|
|
||
|
% Add a new key - which may be present so value to be appended
|
||
|
Key = lists:concat(["key-", N]),
|
||
|
Hash = hash(Key),
|
||
|
case dict:find(Hash, D) of
|
||
|
error ->
|
||
|
go_dict(dict:store(Hash, [N], D), N-1, M);
|
||
|
{ok, List} ->
|
||
|
go_dict(dict:store(Hash, [N|List], D), N-1, M)
|
||
|
end.
|
||
|
|
||
|
|
||
|
|
||
|
%%
|
||
|
%% Timings (microseconds):
|
||
|
%%
|
||
|
%% go_ets(200000) : 609119
|
||
|
%% go_ets(1000000) : 3520757
|
||
|
%% go_ets(5000000) : 19974562
|
||
|
|
||
|
go_ets(N) ->
|
||
|
go_ets(ets:new(ets_test, [private, bag]), N, N).
|
||
|
|
||
|
go_ets(_, 0, _) ->
|
||
|
{erlang:memory(), statistics(garbage_collection)};
|
||
|
go_ets(Ets, N, M) ->
|
||
|
% Lookup a random key - which may not be present
|
||
|
LookupKey = lists:concat(["key-", random:uniform(M)]),
|
||
|
LookupHash = hash(LookupKey),
|
||
|
ets:lookup(Ets, LookupHash),
|
||
|
|
||
|
% Add a new key - which may be present so value to be appended
|
||
|
Key = lists:concat(["key-", N]),
|
||
|
Hash = hash(Key),
|
||
|
ets:insert(Ets, {Hash, N}),
|
||
|
go_ets(Ets, N - 1, M).
|
||
|
|
||
|
%%
|
||
|
%% Timings (microseconds):
|
||
|
%%
|
||
|
%% go_gbtree(200000) : 1393936
|
||
|
%% go_gbtree(1000000) : 8430997
|
||
|
%% go_gbtree(5000000) : 45630810
|
||
|
|
||
|
go_gbtree(N) ->
|
||
|
go_gbtree(gb_trees:empty(), N, N).
|
||
|
|
||
|
go_gbtree(_, 0, _) ->
|
||
|
{erlang:memory(), statistics(garbage_collection)};
|
||
|
go_gbtree(Tree, N, M) ->
|
||
|
% Lookup a random key - which may not be present
|
||
|
LookupKey = lists:concat(["key-", random:uniform(M)]),
|
||
|
LookupHash = hash(LookupKey),
|
||
|
gb_trees:lookup(LookupHash, Tree),
|
||
|
|
||
|
% Add a new key - which may be present so value to be appended
|
||
|
Key = lists:concat(["key-", N]),
|
||
|
Hash = hash(Key),
|
||
|
case gb_trees:lookup(Hash, Tree) of
|
||
|
none ->
|
||
|
go_gbtree(gb_trees:insert(Hash, [N], Tree), N - 1, M);
|
||
|
{value, List} ->
|
||
|
go_gbtree(gb_trees:update(Hash, [N|List], Tree), N - 1, M)
|
||
|
end.
|
||
|
|
||
|
|
||
|
%%
|
||
|
%% Timings (microseconds):
|
||
|
%%
|
||
|
%% go_arrayofidict(200000) : 1266931
|
||
|
%% go_arrayofidict(1000000) : 7387219
|
||
|
%% go_arrayofidict(5000000) : 49511484
|
||
|
|
||
|
go_arrayofdict(N) ->
|
||
|
go_arrayofdict(array:new(256, {default, dict:new()}), N, N).
|
||
|
|
||
|
go_arrayofdict(_, 0, _) ->
|
||
|
% dict:to_list(array:get(0, Array)),
|
||
|
% dict:to_list(array:get(1, Array)),
|
||
|
% dict:to_list(array:get(2, Array)),
|
||
|
% dict:to_list(array:get(3, Array)),
|
||
|
% dict:to_list(array:get(4, Array)),
|
||
|
% dict:to_list(array:get(5, Array)),
|
||
|
% dict:to_list(array:get(6, Array)),
|
||
|
% dict:to_list(array:get(7, Array)),
|
||
|
% dict:to_list(array:get(8, Array)),
|
||
|
% dict:to_list(array:get(9, Array)),
|
||
|
{erlang:memory(), statistics(garbage_collection)};
|
||
|
go_arrayofdict(Array, N, M) ->
|
||
|
% Lookup a random key - which may not be present
|
||
|
LookupKey = lists:concat(["key-", random:uniform(M)]),
|
||
|
LookupHash = hash(LookupKey),
|
||
|
LookupIndex = hash_to_index(LookupHash),
|
||
|
dict:find(LookupHash, array:get(LookupIndex, Array)),
|
||
|
|
||
|
% Add a new key - which may be present so value to be appended
|
||
|
Key = lists:concat(["key-", N]),
|
||
|
Hash = hash(Key),
|
||
|
Index = hash_to_index(Hash),
|
||
|
D = array:get(Index, Array),
|
||
|
case dict:find(Hash, D) of
|
||
|
error ->
|
||
|
go_arrayofdict(array:set(Index,
|
||
|
dict:store(Hash, [N], D), Array), N-1, M);
|
||
|
{ok, List} ->
|
||
|
go_arrayofdict(array:set(Index,
|
||
|
dict:store(Hash, [N|List], D), Array), N-1, M)
|
||
|
end.
|
||
|
|
||
|
%%
|
||
|
%% Timings (microseconds):
|
||
|
%%
|
||
|
%% go_arrayofgbtree(200000) : 1176224
|
||
|
%% go_arrayofgbtree(1000000) : 7480653
|
||
|
%% go_arrayofgbtree(5000000) : 41266701
|
||
|
|
||
|
go_arrayofgbtree(N) ->
|
||
|
go_arrayofgbtree(array:new(256, {default, gb_trees:empty()}), N, N).
|
||
|
|
||
|
go_arrayofgbtree(_, 0, _) ->
|
||
|
% gb_trees:to_list(array:get(0, Array)),
|
||
|
% gb_trees:to_list(array:get(1, Array)),
|
||
|
% gb_trees:to_list(array:get(2, Array)),
|
||
|
% gb_trees:to_list(array:get(3, Array)),
|
||
|
% gb_trees:to_list(array:get(4, Array)),
|
||
|
% gb_trees:to_list(array:get(5, Array)),
|
||
|
% gb_trees:to_list(array:get(6, Array)),
|
||
|
% gb_trees:to_list(array:get(7, Array)),
|
||
|
% gb_trees:to_list(array:get(8, Array)),
|
||
|
% gb_trees:to_list(array:get(9, Array)),
|
||
|
{erlang:memory(), statistics(garbage_collection)};
|
||
|
go_arrayofgbtree(Array, N, M) ->
|
||
|
% Lookup a random key - which may not be present
|
||
|
LookupKey = lists:concat(["key-", random:uniform(M)]),
|
||
|
LookupHash = hash(LookupKey),
|
||
|
LookupIndex = hash_to_index(LookupHash),
|
||
|
gb_trees:lookup(LookupHash, array:get(LookupIndex, Array)),
|
||
|
|
||
|
% Add a new key - which may be present so value to be appended
|
||
|
Key = lists:concat(["key-", N]),
|
||
|
Hash = hash(Key),
|
||
|
Index = hash_to_index(Hash),
|
||
|
Tree = array:get(Index, Array),
|
||
|
case gb_trees:lookup(Hash, Tree) of
|
||
|
none ->
|
||
|
go_arrayofgbtree(array:set(Index,
|
||
|
gb_trees:insert(Hash, [N], Tree), Array), N - 1, M);
|
||
|
{value, List} ->
|
||
|
go_arrayofgbtree(array:set(Index,
|
||
|
gb_trees:update(Hash, [N|List], Tree), Array), N - 1, M)
|
||
|
end.
|
||
|
|
||
|
|
||
|
%%
|
||
|
%% Timings (microseconds):
|
||
|
%%
|
||
|
%% go_arrayofdict_withcache(200000) : 1432951
|
||
|
%% go_arrayofdict_withcache(1000000) : 9140169
|
||
|
%% go_arrayofdict_withcache(5000000) : 59435511
|
||
|
|
||
|
go_arrayofdict_withcache(N) ->
|
||
|
go_arrayofdict_withcache({array:new(256, {default, dict:new()}),
|
||
|
array:new(256, {default, dict:new()})}, N, N).
|
||
|
|
||
|
go_arrayofdict_withcache(_, 0, _) ->
|
||
|
{erlang:memory(), statistics(garbage_collection)};
|
||
|
go_arrayofdict_withcache({MArray, CArray}, N, M) ->
|
||
|
% Lookup a random key - which may not be present
|
||
|
LookupKey = lists:concat(["key-", random:uniform(M)]),
|
||
|
LookupHash = hash(LookupKey),
|
||
|
LookupIndex = hash_to_index(LookupHash),
|
||
|
dict:find(LookupHash, array:get(LookupIndex, CArray)),
|
||
|
dict:find(LookupHash, array:get(LookupIndex, MArray)),
|
||
|
|
||
|
% Add a new key - which may be present so value to be appended
|
||
|
Key = lists:concat(["key-", N]),
|
||
|
Hash = hash(Key),
|
||
|
Index = hash_to_index(Hash),
|
||
|
Cache = array:get(Index, CArray),
|
||
|
case dict:find(Hash, Cache) of
|
||
|
error ->
|
||
|
UpdCache = dict:store(Hash, [N], Cache);
|
||
|
{ok, _} ->
|
||
|
UpdCache = dict:append(Hash, N, Cache)
|
||
|
end,
|
||
|
case dict:size(UpdCache) of
|
||
|
?CACHE_SIZE ->
|
||
|
UpdCArray = array:set(Index, dict:new(), CArray),
|
||
|
UpdMArray = array:set(Index, dict:merge(fun merge_values/3, UpdCache, array:get(Index, MArray)), MArray),
|
||
|
go_arrayofdict_withcache({UpdMArray, UpdCArray}, N - 1, M);
|
||
|
_ ->
|
||
|
UpdCArray = array:set(Index, UpdCache, CArray),
|
||
|
go_arrayofdict_withcache({MArray, UpdCArray}, N - 1, M)
|
||
|
end.
|
||
|
|
||
|
|
||
|
|
||
|
merge_values(_, Value1, Value2) ->
|
||
|
lists:append(Value1, Value2).
|
||
|
|
||
|
|
||
|
|