diff options
Diffstat (limited to 'lib/mnesia/test/mnesia_cost.erl')
-rw-r--r-- | lib/mnesia/test/mnesia_cost.erl | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/lib/mnesia/test/mnesia_cost.erl b/lib/mnesia/test/mnesia_cost.erl new file mode 100644 index 0000000000..54cb2b3064 --- /dev/null +++ b/lib/mnesia/test/mnesia_cost.erl @@ -0,0 +1,222 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(mnesia_cost). +-compile(export_all). + +%% This code exercises the mnesia system and produces a bunch +%% of measurements on what various things cost + +-define(TIMES, 1000). %% set to at least 1000 when running for real !! + +%% This is the record we perform all ops on in this test + +-record(item, {a = 1234, + b = foobar, + c = "1.2.3.4", + d = {'Lennart', 'Hyland'}, + e = true + }). + +go() -> + go([node() | nodes()]). + +go(Nodes) when hd(Nodes) == node() -> + {ok, Out} = file:open("MNESIA_COST", write), + put(out, Out), + + rpc:multicall(Nodes, mnesia, lkill, []), + ok = mnesia:delete_schema(Nodes), + ok = mnesia:create_schema(Nodes), + rpc:multicall(Nodes, mnesia, start, []), + TabDef = [{attributes, record_info(fields, item)}], + {atomic, ok} = mnesia:create_table(item, TabDef), + + round("single ram copy", "no index"), + {atomic, ok} = mnesia:add_table_index(item, #item.e), + round("single ram copy", "One index"), + + {atomic, ok} = mnesia:add_table_index(item, #item.c), + round("single ram copy", "Two indexes"), + + {atomic, ok} = mnesia:del_table_index(item, #item.e), + {atomic, ok} = mnesia:del_table_index(item, #item.c), + + {atomic, ok} = mnesia:change_table_copy_type(item, node(), disc_copies), + round("single disc copy", "no index"), + + {atomic, ok} = mnesia:change_table_copy_type(item, node(), ram_copies), + + case length(Nodes) of + Len when Len < 2 -> + format("<WARNING> replication skipped. Too few nodes.", []); + _Len -> + N2 = lists:nth(2, Nodes), + {atomic, ok} = mnesia:add_table_copy(item, N2, ram_copies), + round("2 replicated ram copy", "no index") + end, + file:close(Out), + erase(out), + ok. + +round(Replication, Index) -> + run(Replication, Index, [write], + fun() -> mnesia:write(#item{}) end), + + + run(Replication, Index, [read], + fun() -> mnesia:read({item, 1234}) end), + + run(Replication, Index, [read, write], + fun() -> mnesia:read({item, 1234}), + mnesia:write(#item{}) end), + + run(Replication, Index, [wread, write], + fun() -> mnesia:wread({item, 1234}), + mnesia:write(#item{}) end), + + + run(Replication, Index, [match, write, write, write], + fun() -> mnesia:match_object({item, 1, '_', '_', '_', true}), + mnesia:write(#item{a =1}), + mnesia:write(#item{a =2}), + mnesia:write(#item{a =3}) end). + + +format(F, As) -> + io:format(get(out), F, As). + +run(What, OtherInfo, Ops, F) -> + run(t, What, OtherInfo, Ops, F). + +run(How, What, OtherInfo, Ops, F) -> + T1 = erlang:now(), + statistics(runtime), + do_times(How, ?TIMES, F), + {_, RunTime} = statistics(runtime), + T2 = erlang:now(), + RealTime = subtr(T1, T2), + report(How, What, OtherInfo, Ops, RunTime, RealTime). + +report(t, What, OtherInfo, Ops, RunTime, RealTime) -> + format("~s, ~s, transaction call ", [What, OtherInfo]), + format("Ops is ", []), + lists:foreach(fun(Op) -> format("~w-", [Op]) end, Ops), + + format("~n ~w/~w Millisecs/Trans ~w/~w MilliSecs/Operation ~n~n", + [RunTime/?TIMES, + RealTime/?TIMES, + RunTime/(?TIMES*length(Ops)), + RealTime/(?TIMES*length(Ops))]); + +report(dirty, What, OtherInfo, Ops, RunTime, RealTime) -> + format("~s, ~s, dirty calls ", [What, OtherInfo]), + format("Ops is ", []), + lists:foreach(fun(Op) -> format("~w-", [Op]) end, Ops), + + format("~n ~w/~w Millisecs/Bunch ~w/~w MilliSecs/Operation ~n~n", + [RunTime/?TIMES, + RealTime/?TIMES, + RunTime/(?TIMES*length(Ops)), + RealTime/(?TIMES*length(Ops))]). + + +subtr(Before, After) -> + E =(element(1,After)*1000000000000 + +element(2,After)*1000000+element(3,After)) - + (element(1,Before)*1000000000000 + +element(2,Before)*1000000+element(3,Before)), + E div 1000. + +do_times(t, I, F) -> + do_trans_times(I, F); +do_times(dirty, I, F) -> + do_dirty(I, F). + +do_trans_times(I, F) when I /= 0 -> + {atomic, _} = mnesia:transaction(F), + do_trans_times(I-1, F); +do_trans_times(_,_) -> ok. + +do_dirty(I, F) when I /= 0 -> + F(), + do_dirty(I-1, F); +do_dirty(_,_) -> ok. + + + +table_load([N1,N2| _ ] = Ns) -> + Nodes = [N1,N2], + rpc:multicall(Ns, mnesia, lkill, []), + ok = mnesia:delete_schema(Ns), + ok = mnesia:create_schema(Nodes), + rpc:multicall(Nodes, mnesia, start, []), + TabDef = [{disc_copies,[N1]},{ram_copies,[N2]}, + {attributes,record_info(fields,item)},{record_name,item}], + Tabs = [list_to_atom("tab" ++ integer_to_list(I)) || I <- lists:seq(1,400)], + + [mnesia:create_table(Tab,TabDef) || Tab <- Tabs], + +%% InitTab = fun(Tab) -> +%% mnesia:write_lock_table(Tab), +%% InitRec = fun(Key) -> mnesia:write(Tab,#item{a=Key},write) end, +%% lists:foreach(InitRec, lists:seq(1,100)) +%% end, +%% +%% {Time,{atomic,ok}} = timer:tc(mnesia,transaction, [fun() ->lists:foreach(InitTab, Tabs) end]), + mnesia:dump_log(), +%% io:format("Init took ~p msec ~n", [Time/1000]), + rpc:call(N2, mnesia, stop, []), timer:sleep(1000), + mnesia:stop(), timer:sleep(500), + %% Warmup + ok = mnesia:start([{no_table_loaders, 1}]), + timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), + mnesia:dump_log(), + rpc:call(N2, mnesia, dump_log, []), + io:format("Initialized ~n",[]), + + mnesia:stop(), timer:sleep(1000), + ok = mnesia:start([{no_table_loaders, 1}]), + {T1, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), + io:format("Loading from disc with 1 loader ~p msec~n",[T1/1000]), + mnesia:stop(), timer:sleep(1000), + ok = mnesia:start([{no_table_loaders, 4}]), + {T2, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), + io:format("Loading from disc with 4 loader ~p msec~n",[T2/1000]), + + %% Warmup + rpc:call(N2, ?MODULE, remote_load, [Tabs,4]), + io:format("Initialized ~n",[]), + + + T3 = rpc:call(N2, ?MODULE, remote_load, [Tabs,1]), + io:format("Loading from net with 1 loader ~p msec~n",[T3/1000]), + + T4 = rpc:call(N2, ?MODULE, remote_load, [Tabs,4]), + io:format("Loading from net with 4 loader ~p msec~n",[T4/1000]), + + ok. + +remote_load(Tabs,Loaders) -> + ok = mnesia:start([{no_table_loaders, Loaders}]), +%% io:format("~p ~n", [mnesia_controller:get_info(500)]), + {Time, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), + timer:sleep(1000), mnesia:stop(), timer:sleep(1000), + Time. |