diff options
-rw-r--r-- | lib/dialyzer/src/dialyzer.hrl | 9 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 42 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_coordinator.erl | 23 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_succ_typings.erl | 71 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_timing.erl | 51 | ||||
-rw-r--r-- | lib/typer/src/typer.erl | 4 |
6 files changed, 107 insertions, 93 deletions
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl index ebfc6b9731..70ee408f12 100644 --- a/lib/dialyzer/src/dialyzer.hrl +++ b/lib/dialyzer/src/dialyzer.hrl @@ -128,6 +128,7 @@ race_detection = false :: boolean(), behaviours_chk = false :: boolean(), timing = false :: boolean(), + timing_server :: dialyzer_timing:timing_server(), callgraph_file = "" :: file:filename()}). -record(options, {files = [] :: [file:filename()], @@ -156,11 +157,11 @@ %%-------------------------------------------------------------------- --define(timing(Msg,Var,Expr), +-define(timing(Server, Msg, Var, Expr), begin - dialyzer_timing:start_stamp(Msg), + dialyzer_timing:start_stamp(Server, Msg), Var = Expr, - dialyzer_timing:end_stamp(), + dialyzer_timing:end_stamp(Server), Var end). --define(timing(Msg,Expr),?timing(Msg,_T,Expr)). +-define(timing(Server, Msg, Expr),?timing(Server, Msg, _T, Expr)). diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 641b7eb22a..3bbde12481 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -52,7 +52,8 @@ parent :: pid(), plt :: dialyzer_plt:plt(), start_from = byte_code :: start_from(), - use_contracts = true :: boolean() + use_contracts = true :: boolean(), + timing_server :: dialyzer_timing:timing_server() }). -record(server_state, {parent :: pid(), legal_warnings :: [dial_warn_tag()]}). @@ -64,14 +65,15 @@ -spec start(pid(), [dial_warn_tag()], #analysis{}) -> 'ok'. start(Parent, LegalWarnings, Analysis) -> - dialyzer_timing:init(Analysis#analysis.timing), + TimingServer = dialyzer_timing:init(Analysis#analysis.timing), RacesOn = ordsets:is_element(?WARN_RACE_CONDITION, LegalWarnings), - Analysis0 = Analysis#analysis{race_detection = RacesOn}, + Analysis0 = + Analysis#analysis{race_detection = RacesOn, timing_server = TimingServer}, Analysis1 = expand_files(Analysis0), Analysis2 = run_analysis(Analysis1), State = #server_state{parent = Parent, legal_warnings = LegalWarnings}, loop(State, Analysis2, none), - dialyzer_timing:stop(). + dialyzer_timing:stop(TimingServer). run_analysis(Analysis) -> Self = self(), @@ -133,7 +135,8 @@ analysis_start(Parent, Analysis) -> plt = Plt, parent = Parent, start_from = Analysis#analysis.start_from, - use_contracts = Analysis#analysis.use_contracts + use_contracts = Analysis#analysis.use_contracts, + timing_server = Analysis#analysis.timing_server }, Files = ordsets:from_list(Analysis#analysis.files), {Callgraph, NoWarn, TmpCServer0} = compile_and_store(Files, State), @@ -157,7 +160,7 @@ analysis_start(Parent, Analysis) -> dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes, TmpCServer1), TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2), - ?timing("remote", + ?timing(State#analysis_state.timing_server, "remote", dialyzer_contracts:process_contract_remote_types(TmpCServer3)) catch throw:{error, _ErrorMsg} = Error -> exit(Error) @@ -186,22 +189,23 @@ analysis_start(Parent, Analysis) -> send_codeserver_plt(Parent, CServer, State3#analysis_state.plt), send_analysis_done(Parent, Plt2, State3#analysis_state.doc_plt). -analyze_callgraph(Callgraph, State) -> - Codeserver = State#analysis_state.codeserver, - Parent = State#analysis_state.parent, - DocPlt = State#analysis_state.doc_plt, +analyze_callgraph(Callgraph, #analysis_state{codeserver = Codeserver, + doc_plt = DocPlt, + timing_server = TimingServer, + parent = Parent} = State) -> Plt = dialyzer_plt:insert_callbacks(State#analysis_state.plt, Codeserver), {NewPlt, NewDocPlt} = case State#analysis_state.analysis_type of plt_build -> - {dialyzer_succ_typings:analyze_callgraph(Callgraph, Plt, - Codeserver, Parent), - DocPlt}; + NewPlt0 = + dialyzer_succ_typings:analyze_callgraph(Callgraph, Plt, Codeserver, + TimingServer, Parent), + {NewPlt0, DocPlt}; succ_typings -> NoWarn = State#analysis_state.no_warn_unused, {Warnings, NewPlt0, NewDocPlt0} = - dialyzer_succ_typings:get_warnings(Callgraph, Plt, DocPlt, - Codeserver, NoWarn, Parent), + dialyzer_succ_typings:get_warnings(Callgraph, Plt, DocPlt, Codeserver, + NoWarn, TimingServer, Parent), send_warnings(State#analysis_state.parent, Warnings), {NewPlt0, NewDocPlt0} end, @@ -234,14 +238,16 @@ make_compile_init(#analysis_state{codeserver = Codeserver, start_from = StartFrom}. compile_and_store(Files, #analysis_state{codeserver = CServer, + timing_server = Timing, parent = Parent} = State) -> send_log(Parent, "Reading files and computing callgraph... "), {T1, _} = statistics(runtime), Callgraph = dialyzer_callgraph:new(), CompileInit = make_compile_init(State, Callgraph), {{Failed, NoWarn, Modules}, NextLabel} = - ?timing("compile", - dialyzer_coordinator:parallel_job(compile, Files, CompileInit)), + ?timing(Timing, "compile", _C1, + dialyzer_coordinator:parallel_job(compile, Files, + CompileInit, Timing)), CServer2 = dialyzer_codeserver:set_next_core_label(NextLabel, CServer), case Failed =:= [] of true -> @@ -259,7 +265,7 @@ compile_and_store(Files, #analysis_state{codeserver = CServer, Msg1 = io_lib:format("done in ~.2f secs\nRemoving edges... ", [(T2-T1)/1000]), send_log(Parent, Msg1), Callgraph = - ?timing("clean", _C3, + ?timing(Timing, "clean", _C2, cleanup_callgraph(State, CServer2, Callgraph, Modules)), {T3, _} = statistics(runtime), Msg2 = io_lib:format("done in ~.2f secs\n", [(T3-T2)/1000]), diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl index e81da5c456..b91fc95959 100644 --- a/lib/dialyzer/src/dialyzer_coordinator.erl +++ b/lib/dialyzer/src/dialyzer_coordinator.erl @@ -26,7 +26,7 @@ -module(dialyzer_coordinator). %%% Export for dialyzer main process --export([parallel_job/3]). +-export([parallel_job/4]). %%% Exports for all possible workers -export([wait_activation/0, job_done/3]). @@ -44,6 +44,7 @@ -define(MAP, dialyzer_coordinator_map). -type coordinator() :: {pid(), pid()}. %%opaque +-type timing() :: dialyzer_timing:timing_server(). -type scc() :: [mfa_or_funlbl()]. -type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'. @@ -85,20 +86,20 @@ %%-------------------------------------------------------------------- --spec parallel_job('compile', compile_jobs(), compile_init_data()) -> +-spec parallel_job('compile', compile_jobs(), compile_init_data(), timing()) -> {compile_result(), integer()}; - ('typesig', typesig_jobs(), typesig_init_data()) -> + ('typesig', typesig_jobs(), typesig_init_data(), timing()) -> typesig_result(); - ('dataflow', dataflow_jobs(), dataflow_init_data()) -> - dataflow_result(); - ('warnings', warnings_jobs(), warnings_init_data()) -> - warnings_result(). + ('dataflow', dataflow_jobs(), dataflow_init_data(), + timing()) -> dataflow_result(); + ('warnings', warnings_jobs(), warnings_init_data(), + timing()) -> warnings_result(). -parallel_job(Mode, Jobs, InitData) -> - State = spawn_jobs(Mode, Jobs, InitData), +parallel_job(Mode, Jobs, InitData, Timing) -> + State = spawn_jobs(Mode, Jobs, InitData, Timing), collect_result(State). -spawn_jobs(Mode, Jobs, InitData) -> +spawn_jobs(Mode, Jobs, InitData, Timing) -> Collector = self(), Regulator = spawn_regulator(), Coordinator = {Collector, Regulator}, @@ -123,7 +124,7 @@ spawn_jobs(Mode, Jobs, InitData) -> 'typesig' -> "SCCs"; _ -> "modules" end, - dialyzer_timing:send_size_info(JobCount, Unit), + dialyzer_timing:send_size_info(Timing, JobCount, Unit), InitResult = case Mode of 'compile' -> dialyzer_analysis_callgraph:compile_init_result(); diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index 9f61f9ff6f..9ca5a66dab 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -28,8 +28,8 @@ -module(dialyzer_succ_typings). -export([analyze_callgraph/3, - analyze_callgraph/4, - get_warnings/6 + analyze_callgraph/5, + get_warnings/7 ]). -export([ @@ -74,6 +74,7 @@ codeserver :: dialyzer_codeserver:codeserver(), no_warn_unused :: set(), parent = none :: parent(), + timing_server :: dialyzer_timing:timing_server(), plt :: dialyzer_plt:plt()}). %%-------------------------------------------------------------------- @@ -83,33 +84,38 @@ dialyzer_plt:plt(). analyze_callgraph(Callgraph, Plt, Codeserver) -> - analyze_callgraph(Callgraph, Plt, Codeserver, none). + analyze_callgraph(Callgraph, Plt, Codeserver, none, none). -spec analyze_callgraph(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(), - dialyzer_codeserver:codeserver(), parent()) -> + dialyzer_codeserver:codeserver(), + dialyzer_timing:timing_server(), parent()) -> dialyzer_plt:plt(). -analyze_callgraph(Callgraph, Plt, Codeserver, Parent) -> +analyze_callgraph(Callgraph, Plt, Codeserver, TimingServer, Parent) -> NewState = - init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent), + init_state_and_get_success_typings(Callgraph, Plt, Codeserver, + TimingServer, Parent), dialyzer_plt:restore_full_plt(NewState#st.plt, Plt). %%-------------------------------------------------------------------- -init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent) -> +init_state_and_get_success_typings(Callgraph, Plt, Codeserver, + TimingServer, Parent) -> {SCCs, Callgraph1} = - ?timing("order", dialyzer_callgraph:finalize(Callgraph)), + ?timing(TimingServer, "order", dialyzer_callgraph:finalize(Callgraph)), State = #st{callgraph = Callgraph1, plt = dialyzer_plt:get_mini_plt(Plt), - codeserver = Codeserver, parent = Parent}, + codeserver = Codeserver, parent = Parent, + timing_server = TimingServer}, get_refined_success_typings(SCCs, State). -get_refined_success_typings(SCCs, #st{callgraph = Callgraph} = State) -> +get_refined_success_typings(SCCs, #st{callgraph = Callgraph, + timing_server = TimingServer} = State) -> case find_succ_typings(SCCs, State) of {fixpoint, State1} -> State1; {not_fixpoint, NotFixpoint1, State1} -> {ModulePostorder, ModCallgraph} = ?timing( - "order", _C1, + TimingServer, "order", _C1, dialyzer_callgraph:module_postorder_from_funs(NotFixpoint1, Callgraph)), ModState = State1#st{callgraph = ModCallgraph}, @@ -119,7 +125,7 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph} = State) -> {not_fixpoint, NotFixpoint2, State2} -> %% Need to reset the callgraph. {NewSCCs, Callgraph2} = - ?timing("order", _C2, + ?timing(TimingServer, "order", _C2, dialyzer_callgraph:reset_from_funs(NotFixpoint2, ModCallgraph)), NewState = State2#st{callgraph = Callgraph2}, @@ -130,12 +136,14 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph} = State) -> -type doc_plt() :: 'undefined' | dialyzer_plt:plt(). -spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(), doc_plt(), dialyzer_codeserver:codeserver(), set(), - pid()) -> + dialyzer_timing:timing_server(), pid()) -> {[dial_warning()], dialyzer_plt:plt(), doc_plt()}. -get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) -> +get_warnings(Callgraph, Plt, DocPlt, Codeserver, + NoWarnUnused, TimingServer, Parent) -> InitState = - init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent), + init_state_and_get_success_typings(Callgraph, Plt, Codeserver, + TimingServer, Parent), NewState = InitState#st{no_warn_unused = NoWarnUnused}, Mods = dialyzer_callgraph:modules(NewState#st.callgraph), MiniPlt = NewState#st.plt, @@ -143,22 +151,22 @@ get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) -> dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver, MiniPlt), MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt), ModWarns = - ?timing("warning", get_warnings_from_modules(Mods, NewState, MiniDocPlt)), + ?timing(TimingServer, "warning", + get_warnings_from_modules(Mods, NewState, MiniDocPlt)), {postprocess_warnings(CWarns ++ ModWarns, Codeserver), dialyzer_plt:restore_full_plt(MiniPlt, Plt), dialyzer_plt:restore_full_plt(MiniDocPlt, DocPlt)}. get_warnings_from_modules(Mods, State, DocPlt) -> #st{callgraph = Callgraph, codeserver = Codeserver, - no_warn_unused = NoWarnUnused, plt = Plt} = State, - Init = {Callgraph, Codeserver, NoWarnUnused, Plt, DocPlt}, - dialyzer_coordinator:parallel_job(warnings, Mods, Init). + no_warn_unused = NoWarnUnused, plt = Plt, + timing_server = TimingServer} = State, + Init = {Codeserver, Callgraph, NoWarnUnused, Plt, DocPlt}, + dialyzer_coordinator:parallel_job(warnings, Mods, Init, TimingServer). --type warning_servers() :: term(). +-spec collect_warnings(module(), warnings_init_data()) -> [dial_warning()]. --spec collect_warnings(module(), warning_servers()) -> [dial_warning()]. - -collect_warnings(M, {Callgraph, Codeserver, NoWarnUnused, Plt, DocPlt}) -> +collect_warnings(M, {Codeserver, Callgraph, NoWarnUnused, Plt, DocPlt}) -> ModCode = dialyzer_codeserver:lookup_mod_code(M, Codeserver), Records = dialyzer_codeserver:lookup_mod_records(M, Codeserver), Contracts = dialyzer_codeserver:lookup_mod_contracts(M, Codeserver), @@ -212,13 +220,14 @@ postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest], end. refine_succ_typings(Modules, #st{codeserver = Codeserver, - callgraph = Callgraph, - plt = Plt} = State) -> - ?debug("Module postorder: ~p\n", [ModulePostorder]), + callgraph = Callgraph, + plt = Plt, + timing_server = Timing} = State) -> + ?debug("Module postorder: ~p\n", [Modules]), Init = {Codeserver, Callgraph, Plt}, NotFixpoint = - ?timing("refine", - dialyzer_coordinator:parallel_job(dataflow, Modules, Init)), + ?timing(Timing, "refine", + dialyzer_coordinator:parallel_job(dataflow, Modules, Init, Timing)), ?debug("==================== Dataflow done ====================\n\n", []), case NotFixpoint =:= [] of true -> {fixpoint, State}; @@ -313,11 +322,11 @@ compare_types_1([], [], _Strict, NotFixpoint) -> end. find_succ_typings(SCCs, #st{codeserver = Codeserver, callgraph = Callgraph, - plt = Plt} = State) -> + plt = Plt, timing_server = Timing} = State) -> Init = {Codeserver, Callgraph, Plt}, NotFixpoint = - ?timing("typesig", - dialyzer_coordinator:parallel_job(typesig, SCCs, Init)), + ?timing(Timing, "typesig", + dialyzer_coordinator:parallel_job(typesig, SCCs, Init, Timing)), ?debug("==================== Typesig done ====================\n\n", []), case NotFixpoint =:= [] of true -> {fixpoint, State}; diff --git a/lib/dialyzer/src/dialyzer_timing.erl b/lib/dialyzer/src/dialyzer_timing.erl index d5e6d1476d..15d8795a37 100644 --- a/lib/dialyzer/src/dialyzer_timing.erl +++ b/lib/dialyzer/src/dialyzer_timing.erl @@ -26,27 +26,20 @@ -module(dialyzer_timing). --export([init/1, start_stamp/1, send_size_info/2, end_stamp/0, stop/0]). +-export([init/1, start_stamp/2, send_size_info/3, end_stamp/1, stop/1]). --spec init(boolean()) -> ok. +-export_type([timing_server/0]). -init(Active) -> - Pid = spawn_link(fun() -> loop_init(Active) end), - register(?MODULE, Pid), - ok. +-type timing_server() :: pid() | 'none'. -loop_init(Active) -> +-spec init(boolean()) -> timing_server(). + +init(Active) -> case Active of true -> io:format("\n"), - loop(now(), 0, ""); - false -> dummy_loop() - end. - -dummy_loop() -> - receive - {Pid, stop, _Now} -> Pid ! ok; - _ -> dummy_loop() + spawn_link(fun() -> loop(now(), 0, "") end); + false -> none end. loop(LastNow, Size, Unit) -> @@ -73,28 +66,32 @@ loop(LastNow, Size, Unit) -> Pid ! ok end. --spec start_stamp(string()) -> ok. +-spec start_stamp(timing_server(), string()) -> ok. -start_stamp(Msg) -> - ?MODULE ! {stamp, Msg, now()}, +start_stamp(none, _) -> ok; +start_stamp(Pid, Msg) -> + Pid ! {stamp, Msg, now()}, ok. --spec end_stamp() -> ok. +-spec end_stamp(timing_server()) -> ok. -end_stamp() -> - ?MODULE ! {stamp, now()}, +end_stamp(none) -> ok; +end_stamp(Pid) -> + Pid ! {stamp, now()}, ok. --spec send_size_info(integer(), string()) -> ok. +-spec send_size_info(timing_server(), integer(), string()) -> ok. -send_size_info(Size, Unit) -> - ?MODULE ! {size, Size, Unit}, +send_size_info(none, _, _) -> ok; +send_size_info(Pid, Size, Unit) -> + Pid ! {size, Size, Unit}, ok. --spec stop() -> ok. +-spec stop(timing_server()) -> ok. -stop() -> - ?MODULE ! {self(), stop, now()}, +stop(none) -> ok; +stop(Pid) -> + Pid ! {self(), stop, now()}, receive ok -> ok end. diff(T2, T1) -> diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index a6de109766..1e40b8926e 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -83,7 +83,7 @@ start() -> {Args, Analysis} = process_cl_args(), %% io:format("Args: ~p\n", [Args]), %% io:format("Analysis: ~p\n", [Analysis]), - dialyzer_timing:init(false), + Timer = dialyzer_timing:init(false), TrustedFiles = filter_fd(Args#args.trusted, [], fun is_erl_file/1), Analysis2 = extract(Analysis, TrustedFiles), All_Files = get_all_files(Args), @@ -92,7 +92,7 @@ start() -> Analysis4 = collect_info(Analysis3), %% io:format("Final: ~p\n", [Analysis4#analysis.fms]), TypeInfo = get_type_info(Analysis4), - dialyzer_timing:stop(), + dialyzer_timing:stop(Timer), show_or_annotate(TypeInfo), %% io:format("\nTyper analysis finished\n"), erlang:halt(0). |