bench_generate.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 668 行 · 第 1/2 页

ERL
668
字号
gen_trans(C, SessionTab) when C#config.generator_profile == random ->    case random:uniform(100) of        Rand when Rand >   0, Rand =<  25 -> gen_t1(C, SessionTab);        Rand when Rand >  25, Rand =<  50 -> gen_t2(C, SessionTab);        Rand when Rand >  50, Rand =<  70 -> gen_t3(C, SessionTab);        Rand when Rand >  70, Rand =<  85 -> gen_t4(C, SessionTab);        Rand when Rand >  85, Rand =< 100 -> gen_t5(C, SessionTab)    end;gen_trans(C, SessionTab) ->    case C#config.generator_profile of        t1   -> gen_t1(C, SessionTab);        t2   -> gen_t2(C, SessionTab);        t3   -> gen_t3(C, SessionTab);        t4   -> gen_t4(C, SessionTab);        t5   -> gen_t5(C, SessionTab);	ping -> gen_ping(C, SessionTab)    end.        gen_t1(C, SessionTab) ->    SubscrId    = random:uniform(C#config.n_subscribers) - 1,    SubscrKey   = bench_trans:number_to_key(SubscrId, C),    Location    = 4711,    ChangedBy   = <<4711:(8*25)>>,    ChangedTime = <<4711:(8*25)>>,    {t1,     nearest_node(SubscrId, transaction, C),     fun(Wlock) -> bench_trans:update_current_location(Wlock, SubscrKey, Location, ChangedBy, ChangedTime) end,     no_fun    }.gen_t2(C, SessionTab) ->    SubscrId  = random:uniform(C#config.n_subscribers) - 1,    SubscrKey = bench_trans:number_to_key(SubscrId, C),    {t2,     nearest_node(SubscrId, sync_dirty, C),     %%nearest_node(SubscrId, transaction, C),     fun(Wlock) -> bench_trans:read_current_location(Wlock, SubscrKey) end,     no_fun    }.gen_t3(C,  SessionTab) ->    case ets:first(SessionTab) of	'$end_of_table' ->	    %% This generator does not have any session,	    %% try reading someone elses session details	    SubscrId  = random:uniform(C#config.n_subscribers) - 1,	    SubscrKey = bench_trans:number_to_key(SubscrId, C),	    ServerId  = random:uniform(C#config.n_servers) - 1,	    ServerBit = 1 bsl ServerId,	    {t3,	     nearest_node(SubscrId, transaction, C),	     fun(Wlock) -> bench_trans:read_session_details(Wlock, SubscrKey, ServerBit, ServerId) end,	     no_fun	    };	{SubscrId, SubscrKey, ServerId}  ->	    %% This generator do have a session,	    %% read its session details	    ServerBit = 1 bsl ServerId,	    {t3,	     nearest_node(SubscrId, transaction, C),	     fun(Wlock) -> bench_trans:read_session_details(Wlock, SubscrKey, ServerBit, ServerId) end,	     no_fun	    }    end.gen_t4(C, SessionTab) ->    %% This generator may already have sessions,    %% create a new session and hope that no other    %% generator already has occupied it    SubscrId   = random:uniform(C#config.n_subscribers) - 1,    SubscrKey  = bench_trans:number_to_key(SubscrId, C),    ServerId   = random:uniform(C#config.n_servers) - 1,    ServerBit  = 1 bsl ServerId,    Details    = <<4711:(8*2000)>>,    DoRollback = (random:uniform(100) =< 2),    Insert     = fun() -> ets:insert(SessionTab, {{SubscrId, SubscrKey, ServerId}, self()}) end,    {t4,     nearest_node(SubscrId, transaction, C),     fun(Wlock) -> bench_trans:create_session_to_server(Wlock, SubscrKey, ServerBit, ServerId, Details, DoRollback) end,     Insert    }.gen_t5(C, SessionTab) ->    case ets:first(SessionTab) of	'$end_of_table' ->	    %% This generator does not have any session,	    %% try to delete someone elses session details	    SubscrId   = random:uniform(C#config.n_subscribers) - 1,	    SubscrKey  = bench_trans:number_to_key(SubscrId, C),	    ServerId   = random:uniform(C#config.n_servers) - 1,	    ServerBit  = 1 bsl ServerId,	    DoRollback = (random:uniform(100) =< 2),	    {t5,	     nearest_node(SubscrId, transaction, C),	     fun(Wlock) -> bench_trans:delete_session_from_server(Wlock, SubscrKey, ServerBit, ServerId, DoRollback) end,	     no_fun	    };	{SubscrId, SubscrKey, ServerId}  ->	    %% This generator do have at least one session,	    %% delete it.	    ServerBit  = 1 bsl ServerId,		    DoRollback = (random:uniform(100) =< 2),	    Delete     = fun() -> ets:delete(SessionTab, {SubscrId, SubscrKey, ServerId}) end,	    {t5,	     nearest_node(SubscrId, transaction, C),	     fun(Wlock) -> bench_trans:delete_session_from_server(Wlock, SubscrKey, ServerBit, ServerId, DoRollback) end,	     Delete	    }    end.gen_ping(C, SessionTab) ->    SubscrId   = random:uniform(C#config.n_subscribers) - 1,    {ping,     nearest_node(SubscrId, transaction, C),     fun(Wlock) -> {do_commit, true, []} end,     no_fun    }.    %% Select a node as near as the subscriber data as possiblenearest_node(SubscrId, Activity, C) ->    Suffix = bench_trans:number_to_suffix(SubscrId),    case mnesia_frag:table_info(t, s, {suffix, Suffix}, where_to_write) of	[] ->	    {[node()], Activity, write};	[Node] ->	    {[Node], Activity, write};	Nodes ->	    Wlock = C#config.write_lock_type,	    case Wlock of		sticky_write ->		    Node = pick_node(Suffix, C, Nodes),		    {[Node | Nodes], Activity, Wlock};		write ->		    case lists:member(node(), Nodes) of			true ->			    {[node() | Nodes], Activity, Wlock};			false ->			    Node = pick_node(Suffix, C, Nodes),			    {[Node | Nodes], Activity, Wlock}		    end	    end    end.  pick_node(Suffix, C, Nodes) ->    Ordered = lists:sort(Nodes),    NumberOfActive = length(Ordered),    PoolSize = length(C#config.table_nodes),    Suffix2 = 	case PoolSize rem NumberOfActive of	    0 -> Suffix div (PoolSize div NumberOfActive);	    _ -> Suffix	end,    N = (Suffix2 rem NumberOfActive) + 1,    lists:nth(N, Ordered).display_statistics(Stats, C) ->    GoodStats = [{node(GenPid), GenStats} || {GenPid, GenStats} <- Stats,					     list(GenStats)],    FlatStats = [{Type, Name, EvalNode, GenNode, Count} ||                    {GenNode, GenStats} <- GoodStats,                    {{Type, Name, EvalNode}, Count} <- GenStats],    TotalStats = calc_stats_per_tag(lists:keysort(2, FlatStats), 2, []),    {value, {n_aborts, 0, NA, 0, 0}} =     lists:keysearch(n_aborts, 1, TotalStats ++ [{n_aborts, 0, 0, 0, 0}]),    {value, {n_commits, NC, 0, 0, 0}} =	lists:keysearch(n_commits, 1, TotalStats ++ [{n_commits, 0, 0, 0, 0}]),    {value, {n_branches_executed, 0, 0, NB, 0}} =	lists:keysearch(n_branches_executed, 1, TotalStats ++ [{n_branches_executed, 0, 0, 0, 0}]),    {value, {n_micros, 0, 0, 0, AccMicros}} =	lists:keysearch(n_micros, 1, TotalStats ++ [{n_micros, 0, 0, 0, 0}]),    NT = NA + NC,    NG = length(GoodStats),    NTN = length(C#config.table_nodes),    WallMicros = C#config.generator_duration * 1000 * NG,    Overhead = (catch (WallMicros - AccMicros) / WallMicros),    ?d("~n", []),    ?d("Benchmark result...~n", []),    ?d("~n", []),    ?d("    ~p transactions per second (TPS).~n", [catch ((NT * 1000000 * NG) div AccMicros)]),    ?d("    ~p TPS per table node.~n", [catch ((NT * 1000000 * NG) div (AccMicros * NTN))]),    ?d("    ~p micro seconds in average per transaction, including latency.~n",       [catch (AccMicros div NT)]),    ?d("    ~p transactions. ~f% generator overhead.~n", [NT, Overhead * 100]),    TypeStats = calc_stats_per_tag(lists:keysort(1, FlatStats), 1, []),    EvalNodeStats = calc_stats_per_tag(lists:keysort(3, FlatStats), 3, []),    GenNodeStats = calc_stats_per_tag(lists:keysort(4, FlatStats), 4, []),    if	C#config.statistics_detail == normal ->	    ignore;	true ->	    ?d("~n", []),	    ?d("Statistics per transaction type...~n", []),	    ?d("~n", []),	    display_type_stats("    ", TypeStats, NT, AccMicros),	    ?d("~n", []),	    ?d("Transaction statistics per table node...~n", []),	    ?d("~n", []),	    display_calc_stats("    ", EvalNodeStats, NT, AccMicros),	    ?d("~n", []),	    ?d("Transaction statistics per generator node...~n", []),	    ?d("~n", []),	    display_calc_stats("    ", GenNodeStats, NT, AccMicros)    end,    if	C#config.statistics_detail /= debug2 ->	    ignore;	true ->	    io:format("~n", []),	    io:format("------ Test Results ------~n", []),	    io:format("Length        : ~p sec~n", [C#config.generator_duration div 1000]),	    Host = lists:nth(2, string:tokens(atom_to_list(node()), [$@])),	    io:format("Processor     : ~s~n", [Host]),	    io:format("Number of Proc: ~p~n", [NG]),	    io:format("~n", []),	    display_trans_stats("    ", TypeStats, NT, AccMicros, NG),	    io:format("~n", []),	    io:format("  Overall Statistics~n", []),	    io:format("     Transactions: ~p~n", [NT]),	    io:format("     Inner       : ~p TPS~n", [catch ((NT * 1000000 * NG) div AccMicros)]),	    io:format("     Outer       : ~p TPS~n", [catch ((NT * 1000000 * NG) div WallMicros)]),	    io:format("~n", [])    end.     display_calc_stats(Prefix, [{Tag, 0, 0, 0, 0} | Rest], NT, Micros) ->    display_calc_stats(Prefix, Rest, NT, Micros);   display_calc_stats(Prefix, [{Tag, NC, NA, NB, NM} | Rest], NT, Micros) ->    ?d("~s~s n=~s%\ttime=~s%~n",       [Prefix, left(Tag), percent(NC + NA, NT), percent(NM, Micros)]),    display_calc_stats(Prefix, Rest, NT, Micros);   display_calc_stats(_, [], _, _) ->    ok.display_type_stats(Prefix, [{Tag, 0, 0, 0, 0} | Rest], NT, Micros) ->    display_type_stats(Prefix, Rest, NT, Micros);   display_type_stats(Prefix, [{Tag, NC, NA, NB, NM} | Rest], NT, Micros) ->    ?d("~s~s n=~s%\ttime=~s%\tavg micros=~p~n",       [	Prefix,	left(Tag),	percent(NC + NA, NT),	percent(NM, Micros),	catch (NM div (NC + NA))       ]),    case NA /= 0 of	true  -> ?d("~s    ~s% aborted~n", [Prefix, percent(NA, NC + NA)]);	false -> ignore    end,    case NB /= 0 of	true  -> ?d("~s    ~s% branches executed~n", [Prefix, percent(NB, NC + NA)]);	false -> ignore    end,    display_type_stats(Prefix, Rest, NT, Micros);   display_type_stats(_, [], _, _) ->    ok.left(Term) ->    string:left(lists:flatten(io_lib:format("~p", [Term])), 27, $.).percent(Part, 0)     -> "infinity";percent(Part, Total) -> io_lib:format("~8.4f", [(Part * 100) / Total]).calc_stats_per_tag([], Pos, Acc) ->    lists:sort(Acc);calc_stats_per_tag([Tuple | _] = FlatStats, Pos, Acc) when size(Tuple) == 5 ->    Tag = element(Pos, Tuple),    do_calc_stats_per_tag(FlatStats, Pos, {Tag, 0, 0, 0, 0}, Acc).do_calc_stats_per_tag([Tuple | Rest], Pos, {Tag, NC, NA, NB, NM}, Acc)  when element(Pos, Tuple) == Tag ->    Val = element(5, Tuple),    case element(2, Tuple) of        n_commits ->            do_calc_stats_per_tag(Rest, Pos, {Tag, NC + Val, NA, NB, NM}, Acc);        n_aborts ->            do_calc_stats_per_tag(Rest, Pos, {Tag, NC, NA + Val, NB, NM}, Acc);        n_branches_executed ->            do_calc_stats_per_tag(Rest, Pos, {Tag, NC, NA, NB + Val, NM}, Acc);        n_micros ->            do_calc_stats_per_tag(Rest, Pos, {Tag, NC, NA, NB, NM + Val}, Acc)    end;do_calc_stats_per_tag(GenStats, Pos, CalcStats, Acc) ->    calc_stats_per_tag(GenStats, Pos, [CalcStats | Acc]).display_trans_stats(Prefix, [{Tag, 0, 0, 0, 0} | Rest], NT, Micros, NG) ->    display_trans_stats(Prefix, Rest, NT, Micros, NG);   display_trans_stats(Prefix, [{Tag, NC, NA, NB, NM} | Rest], NT, Micros, NG) ->    Common =	fun(Name) ->           Sec = NM / (1000000 * NG),	   io:format("  ~s: ~p (~p%) Time: ~p sec TPS = ~p~n",		     [Name,		      NC + NA,		      round(((NC + NA) * 100) / NT),		      round(Sec),		      round((NC + NA) / Sec)])        end,    Branch = 	fun() ->             io:format("      Branches Executed: ~p (~p%)~n",		      [NB, round((NB * 100) / (NC + NA))])	end,    Rollback =	fun() -> 	            io:format("      Rollback Executed: ~p (~p%)~n",		      [NA, round((NA * 100) / (NC + NA))])	end,    case Tag of	t1 ->	    Common("T1");	t2 ->	    Common("T2");	t3 ->	    Common("T3"),	    Branch();	t4 ->	    Common("T4"),	    Branch(),	    Rollback();	t5 ->	    Common("T5"),	    Branch(),	    Rollback();	_ ->	    Common(io_lib:format("~p", [Tag]))    end,    display_trans_stats(Prefix, Rest, NT, Micros, NG);   display_trans_stats(_, [], _, _, _) ->    ok.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?