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 + -
显示快捷键?