megaco_codec_meas.erl

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

ERL
652
字号
		    io:format("~n", []),		    info(S,[]);		_ ->		    io:format("~n~s skipped~n", [File])	    end,	    measure(Dir, Codec, Conf, Files, Results, MCount)    end.do_measure(Dir, Codec, Conf, File, MCount) ->    BinMsg             = read_message(Dir, File),    {Version, NewBin}  = detect_version(Codec, Conf, BinMsg),    {Msg, Dcnt, Dtime} = measure_decode(Codec, Conf, Version, NewBin, MCount),    {_,   Ecnt, Etime} = measure_encode(Codec, Conf, Version, Msg, MCount),    {ok, #stat{file = File, % 	       ecount = 1, etime = 1, % 	       dcount = 1, dtime = 1, 	       ecount = Ecnt, etime = Etime, 	       dcount = Dcnt, dtime = Dtime, 	       size = size(NewBin)}}.read_message(Dir, FileName) ->    File = filename:join([Dir, FileName]),    case file:read_file_info(File) of        {ok, #file_info{size = Sz, type = regular}} when Sz > 0 ->            case file:read_file(File) of                {ok, Msg} ->		    %% io:format(".", []),                    Msg;                {error, Reason} ->                    S = format("failed reading file ~s: ~p", [File, Reason]),                    throw({error, S})            end;        {ok, #file_info{type = regular}} ->            S = format("skipping empty file ~s", [File]),            throw({info, S});        {ok, #file_info{type = Type}} ->            S = format("skipping ~p file ~s", [Type, File]),            throw({info, S});        {ok, Info} ->            S = format("skipping file ~s~n~p", [File, Info]),            throw({info, S});        {error, Reason} ->            S = format("failed reading file info for ~s: ~p", [File, Reason]),            throw({error, S})    end.detect_version(Codec, Conf, Bin) ->    case (catch Codec:version_of(Conf, Bin)) of	{ok, V} ->	    io:format("[~w]", [V]),	    {ok, M} = Codec:decode_message(Conf, V, Bin),	    {ok, NewBin} = Codec:encode_message(Conf, V, M),	    io:format("[~w]", [size(NewBin)]),	    {V, NewBin};	Error ->	    io:format("~nversion detection failed:~n~p", [Error]),	    Error    end.	    measure_decode(Codec, Conf, Version, Bin, MCount) ->    case measure_codec(Codec, decode_message, Conf, Version, Bin, MCount) of	{ok, Res} ->	    Res;	{error, Reason} ->	    S = format("decode failed for ~p:~n~p", [Codec, Reason]),	    throw({error, S})    end.measure_encode(Codec, Conf, Version, Bin, MCount) ->    case measure_codec(Codec, encode_message, Conf, Version, Bin, MCount) of	{ok, Res} ->	    Res;	{error, Reason} ->	    S = format("encode failed for ~p:~n~p", [Codec, Reason]),	    throw({error, S})    end.measure_codec(Codec, Func, Conf, Version, Bin, MCount) ->    Pid = spawn_link(?MODULE, do_measure_codec,                      [self(), Codec, Func, Conf, Version, Bin, MCount]),    receive	{measure_result, Pid, Func, Res} ->	    {ok, Res};	{error, Pid, Error} ->	    {error, Error};	Else ->	    {error, {unexpected_result, Else}}    after ?MEASURE_TIMEOUT ->	    {error, timeout}    end.do_measure_codec(Parent, Codec, Func, Conf, Version, Bin, MCount) ->    {ok, Count} = measure_warmup(Codec, Func, Conf, Version, Bin, MCount),    Res = timer:tc(?MODULE, do_measure_codec_loop, 		   [Codec, Func, Conf, Version, Bin, Count, dummy]),    case Res of	{Time, {ok, M}} ->	    %% io:format("~w ", [Time]),	    Parent ! {measure_result, self(), Func, {M, Count, Time}};	{_Time, Error} ->	    Parent ! {error, self(), Error}    end,    unlink(Parent). % Make sure Parent don't get our exit signal%% This function does more mor less what the real measure function%% above does. But with the diff:%% 1) Warmup to ensure that all used code are loaded%% 2) To aproximate the encoding time, to ensure that %%    the real encode is done with enough iterations.measure_warmup(Codec, Func, Conf, Version, M, MCount) ->    Res = timer:tc(?MODULE, do_measure_codec_loop, 		   [Codec, Func, Conf, Version, M, MCount, dummy]),    case Res of	{Time, {ok, _}} ->	    %% OK so far, now calculate the count:	    Count = round(?MEASURE_COUNT_TIME/(Time/MCount)),	    %% io:format("~w ", [Count]),	    {ok, Count};	{_Time, Error} ->	    {error, {warmup_failed, Error}}    end.do_measure_codec_loop(_Codec, _Func, _Conf, _Version, _Bin, 0, M) ->    {ok, M};do_measure_codec_loop(Codec, Func, Conf, Version, Bin, Count, _) ->    {ok, M} = apply(Codec, Func, [Conf, Version, Bin]),    do_measure_codec_loop(Codec, Func, Conf, Version, Bin, Count - 1, M).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%store_results(Results) ->    io:format("storing: ~n", []),        store_excel_message_size(Results),    store_excel_decode_time(Results),    store_excel_encode_time(Results),    store_excel_total_time(Results),    io:format("~n", []),    ok.store_excel_message_size(Res) ->    Filename = "message_size.xls",    io:format("  creating ~s~n", [Filename]),    {ok, Fd} = file:open(Filename,[write]),    Sizes = message_sizes(Res, []),    store_excel_tab(Fd, Sizes),    ok.store_excel_decode_time(Res) ->    Filename = "decode_time.xls",    io:format("  creating ~s~n", [Filename]),    {ok, Fd} = file:open(Filename,[write]),    Decodes = dec_times(Res, []),    store_excel_tab(Fd, Decodes),    ok.store_excel_encode_time(Res) ->    Filename = "encode_time.xls",    io:format("  creating ~s~n", [Filename]),    {ok, Fd} = file:open(Filename,[write]),    Encodes = enc_times(Res, []),    store_excel_tab(Fd, Encodes),    ok.store_excel_total_time(Res) ->    Filename = "total_time.xls",    io:format("  creating ~s~n", [Filename]),    {ok, Fd} = file:open(Filename,[write]),    Totals = tot_times(Res, []),    store_excel_tab(Fd, Totals),    ok.message_sizes([], Sizes) ->    lists:reverse(Sizes);message_sizes([{Dir, Conf, Res}|T], Acc) ->    Sizes = [Size || #stat{size = Size} <- Res],    Avg   = avg(Sizes),    message_sizes(T, [{Dir, Conf, Avg, Sizes}|Acc]).dec_times([], Times) ->    lists:reverse(Times);dec_times([{Dir, Conf, Res}|T], Acc) ->    Times = [Time/Count || #stat{dcount = Count, dtime = Time} <- Res],    Avg   = avg(Times),    dec_times(T, [{Dir, Conf, Avg, Times}|Acc]).enc_times([], Times) ->    lists:reverse(Times);enc_times([{Dir, Conf, Res}|T], Acc) ->    Times = [Time/Count || #stat{ecount = Count, etime = Time} <- Res],    Avg   = avg(Times),    enc_times(T, [{Dir, Conf, Avg, Times}|Acc]).tot_times([], Times) ->    lists:reverse(Times);tot_times([{Dir, Conf, Res}|T], Acc) ->    Times = [(Etime/Ecnt)+(Dtime/Dcnt) || #stat{ecount = Ecnt, 						etime  = Etime, 						dcount = Dcnt, 						dtime  = Dtime} <- Res],    Avg   = avg(Times),    tot_times(T, [{Dir, Conf, Avg, Times}|Acc]).avg(Vals) ->    round(lists:sum(Vals)/length(Vals)).store_excel_tab(_Fd, []) ->    ok; % Just in case there was something wrong with the teststore_excel_tab(Fd, Res) ->    %% For all elements of this list, the Values is of the same length...    [{_, _, _, Values}|_] = Res,    store_excel_tab_header(Fd, length(Values), 1),    store_excel_tab1(Fd, Res).store_excel_tab1(Fd, []) ->    io:format(Fd, "~n", []);store_excel_tab1(Fd, [{Dir, Conf, Avg, Values}|T]) when list(Conf) ->    io:format(Fd, "~s~s (~w)", 	      [filename:basename(Dir), config_to_string(Conf), Avg]),    store_excel_tab_row(Fd, Values),    store_excel_tab1(Fd, T).config_to_string([]) ->    "";config_to_string([C]) when atom(C) ->    io_lib:format("_~w", [C]);config_to_string([C|Cs]) when atom(C) ->    lists:flatten(io_lib:format("_~w", [C]) ++ config_to_string(Cs)).store_excel_tab_header(Fd, 0, _) ->    io:format(Fd, "~n", []);store_excel_tab_header(Fd, N, M) ->    io:format(Fd, "\t~w", [M]),    store_excel_tab_header(Fd, N-1, M+1).store_excel_tab_row(Fd, []) ->    io:format(Fd, "~n", []);store_excel_tab_row(Fd, [Value|Values]) ->    io:format(Fd, "\t~w", [round(Value)]),    store_excel_tab_row(Fd, Values).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%start_flex_scanner() ->    Pid = proc_lib:spawn(?MODULE, flex_scanner_handler, [self()]),    receive        {flex_scanner_started, Pid, Conf} ->            {Pid, [Conf]};        {flex_scanner_error, {failed_loading_flex_scanner_driver, Reason}} ->            throw({error, {failed_loading_flex_scanner_driver, Reason}});        {flex_scanner_error, Reason} ->            throw({error, {failed_loading_flex_scanner_driver, Reason}})    after 10000 ->            exit(Pid, kill),            throw({error, {failed_starting_flex_scanner, timeout}})    end.stop_flex_scanner(Pid) ->    Pid ! stop_flex_scanner.flex_scanner_handler(Pid) ->    case (catch megaco_flex_scanner:start()) of        {ok, Port} when port(Port) ->            Pid ! {flex_scanner_started, self(), {flex, Port}},            flex_scanner_handler(Pid, Port);        {error, {load_driver, {open_error, Reason}}} ->            Error = {failed_loading_flex_scanner_driver, Reason},            Pid ! {flex_scanner_error, Error},            exit(Error);        Else ->            Error = {unknown_result_from_start_flex_scanner, Else},            Pid ! {flex_scanner_error, Error},            exit(Error)    end.flex_scanner_handler(Pid, Port) ->    receive        {ping, Pinger} ->            Pinger ! {pong, self()},            flex_scanner_handler(Pid, Port);        {'EXIT', Port, Reason} ->            Pid ! {flex_scanner_exit, Reason},            exit({flex_scanner_exit, Reason});        stop_flex_scanner ->            megaco_flex_scanner:stop(Port),            exit(normal);        Other ->            info("flex scanner handler got something:~n~p", [Other]),            flex_scanner_handler(Pid, Port)    end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%info(F, A) ->    io:format(F ++ "~n", A).error(F, A) ->     io:format("ERROR: " ++ F ++ "~n", A).format(F, A) ->        lists:flatten(io_lib:format(F, A)).

⌨️ 快捷键说明

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