From 60e682897f98d9374b96c6324759f302170b2a17 Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Mon, 20 Feb 2012 13:56:25 +0100 Subject: Add --time option to Dialyzer --- lib/dialyzer/src/Makefile | 1 + lib/dialyzer/src/dialyzer.hrl | 9 +++ lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 3 +- lib/dialyzer/src/dialyzer_cl.erl | 2 + lib/dialyzer/src/dialyzer_cl_parse.erl | 9 ++- lib/dialyzer/src/dialyzer_options.erl | 2 + lib/dialyzer/src/dialyzer_succ_typings.erl | 7 +- lib/dialyzer/src/dialyzer_timing.erl | 88 ++++++++++++++++++++++++ lib/typer/src/typer.erl | 2 + 9 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 lib/dialyzer/src/dialyzer_timing.erl diff --git a/lib/dialyzer/src/Makefile b/lib/dialyzer/src/Makefile index 39b1b3eb3e..09fb02bda2 100644 --- a/lib/dialyzer/src/Makefile +++ b/lib/dialyzer/src/Makefile @@ -63,6 +63,7 @@ MODULES = \ dialyzer_plt \ dialyzer_races \ dialyzer_succ_typings \ + dialyzer_timing \ dialyzer_typesig \ dialyzer_coordinator \ dialyzer_worker \ diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl index 44b1ebeabd..e2edd3f0af 100644 --- a/lib/dialyzer/src/dialyzer.hrl +++ b/lib/dialyzer/src/dialyzer.hrl @@ -132,6 +132,7 @@ -record(options, {files = [] :: [file:filename()], files_rec = [] :: [file:filename()], analysis_type = succ_typings :: anal_type1(), + timing = false :: boolean(), defines = [] :: [dial_define()], from = byte_code :: start_from(), get_warnings = maybe :: boolean() | 'maybe', @@ -153,3 +154,11 @@ forms = [] :: [{_, _}]}). %%-------------------------------------------------------------------- + +-define(timing(Msg,Expr), + begin + dialyzer_timing:start_stamp(Msg), + __T = Expr, + dialyzer_timing:end_stamp(), + __T + end). diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index febaf56e40..30eb087fcf 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -134,7 +134,8 @@ analysis_start(Parent, Analysis) -> use_contracts = Analysis#analysis.use_contracts }, Files = ordsets:from_list(Analysis#analysis.files), - {Callgraph, NoWarn, TmpCServer0} = compile_and_store(Files, State), + {Callgraph, NoWarn, TmpCServer0} = + ?timing("compile",compile_and_store(Files, State)), %% Remote type postprocessing NewCServer = try diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 6d3b1f0531..482f428e02 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -400,8 +400,10 @@ do_analysis(Files, Options, Plt, PltInfo) -> callgraph_file = Options#options.callgraph_file}, State3 = start_analysis(State2, InitAnalysis), {T1, _} = statistics(wall_clock), + ok = dialyzer_timing:init(Options#options.timing), Return = cl_loop(State3), {T2, _} = statistics(wall_clock), + ok = dialyzer_timing:stop(), report_elapsed_time(T1, T2, Options), Return. diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl index ff8fc39a5e..5baba7d11b 100644 --- a/lib/dialyzer/src/dialyzer_cl_parse.erl +++ b/lib/dialyzer/src/dialyzer_cl_parse.erl @@ -164,6 +164,9 @@ cl(["--src"|T]) -> cl(["--no_spec"|T]) -> put(dialyzer_options_use_contracts, false), cl(T); +cl(["--time"|T]) -> + put(dialyzer_timing, true), + cl(T); cl(["-v"|_]) -> io:format("Dialyzer version "++?VSN++"\n"), erlang:halt(?RET_NOTHING_SUSPICIOUS); @@ -250,6 +253,7 @@ init() -> put(dialyzer_output_format, formatted), put(dialyzer_filename_opt, basename), put(dialyzer_options_check_plt, DefaultOpts#options.check_plt), + put(dialyzer_timing, DefaultOpts#options.timing), ok. append_defines([Def, Val]) -> @@ -290,6 +294,7 @@ cl_options() -> {filename_opt, get(dialyzer_filename_opt)}, {analysis_type, get(dialyzer_options_analysis_type)}, {get_warnings, get(dialyzer_options_get_warnings)}, + {timing, get(dialyzer_timing)}, {callgraph_file, get(dialyzer_callgraph_file)} |common_options()]. @@ -351,7 +356,7 @@ help_message() -> [--apps applications] [-o outfile] [--build_plt] [--add_to_plt] [--remove_from_plt] [--check_plt] [--no_check_plt] [--plt_info] [--get_warnings] - [--no_native] [--fullpath] + [--no_native] [--fullpath] [--time] Options: files_or_dirs (for backwards compatibility also as: -c files_or_dirs) Use Dialyzer from the command line to detect defects in the @@ -418,6 +423,8 @@ Options: Make Dialyzer a bit more quiet. --verbose Make Dialyzer a bit more verbose. + --time + Print time information --build_plt The analysis starts from an empty plt and creates a new one from the files specified with -c and -r. Only works for beam files. diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl index 866650a0b2..a1e316d6cc 100644 --- a/lib/dialyzer/src/dialyzer_options.erl +++ b/lib/dialyzer/src/dialyzer_options.erl @@ -194,6 +194,8 @@ build_options([{OptionName, Value} = Term|Rest], Options) -> callgraph_file -> assert_filename(Value), build_options(Rest, Options#options{callgraph_file = Value}); + timing -> + build_options(Rest, Options#options{timing = Value}); _ -> bad_option("Unknown dialyzer command line option", Term) end; diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index 4d813e06bb..e901677ce2 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -132,7 +132,8 @@ get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) -> NewState#st.plt), MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt), {Warnings, FinalPlt, FinalDocPlt} = - get_warnings_from_modules(Mods, NewState, MiniDocPlt, CWarns), + ?timing("warning", + get_warnings_from_modules(Mods, NewState, MiniDocPlt, CWarns)), {postprocess_warnings(Warnings, Codeserver), dialyzer_plt:restore_full_plt(FinalPlt, Plt), dialyzer_plt:restore_full_plt(FinalDocPlt, DocPlt)}. @@ -201,7 +202,7 @@ refine_succ_typings(ModulePostorder, #st{codeserver = Codeserver, ?debug("Module postorder: ~p\n", [ModulePostorder]), Servers = {Codeserver, Callgraph, Plt}, Coordinator = dialyzer_coordinator:start(dataflow, Servers), - refine_succ_typings(ModulePostorder, State, Coordinator). + ?timing("refine",refine_succ_typings(ModulePostorder, State, Coordinator)). refine_succ_typings([M|Rest], State, Coordinator) -> Msg = io_lib:format("Dataflow of module: ~w\n", [M]), @@ -315,7 +316,7 @@ find_succ_typings(SCCs, #st{codeserver = Codeserver, callgraph = Callgraph, plt = Plt} = State) -> Servers = {Codeserver, dialyzer_callgraph:mini_callgraph(Callgraph), Plt}, Coordinator = dialyzer_coordinator:start(typesig, Servers), - find_succ_typings(SCCs, State, Coordinator). + ?timing("typesig", find_succ_typings(SCCs, State, Coordinator)). find_succ_typings([SCC|Rest], #st{parent = Parent} = State, Coordinator) -> Msg = io_lib:format("Typesig analysis for SCC: ~w\n", [format_scc(SCC)]), diff --git a/lib/dialyzer/src/dialyzer_timing.erl b/lib/dialyzer/src/dialyzer_timing.erl new file mode 100644 index 0000000000..73dbbf5a34 --- /dev/null +++ b/lib/dialyzer/src/dialyzer_timing.erl @@ -0,0 +1,88 @@ +%% -*- erlang-indent-level: 2 -*- +%%------------------------------------------------------------------- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2012. 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% +%% + +%%%------------------------------------------------------------------- +%%% File : dialyzer_timing.erl +%%% Authors : Stavros Aronis +%%% Description : Timing reports for Dialyzer +%%%------------------------------------------------------------------- + +-module(dialyzer_timing). + +-export([init/1, start_stamp/1, end_stamp/0, stop/0]). + +-spec init(boolean()) -> ok. + +init(Active) -> + Pid = spawn(fun() -> loop_init(Active) end), + case whereis(?MODULE) of + undefined -> ok; + _ -> unregister(?MODULE) + end, + register(?MODULE, Pid), + ok. + +loop_init(Active) -> + case Active of + true -> + io:format("\n"), + loop(now()); + false -> dummy_loop() + end. + +dummy_loop() -> + receive + {Pid, stop, _Now} -> Pid ! ok; + _ -> dummy_loop() + end. + +loop(LastNow) -> + receive + {stamp, Msg, Now} -> + io:format("~s\t(+~6.2fs): ", [Msg, diff(Now, LastNow)]), + loop(Now); + {stamp, Now} -> + io:format("~6.2fs\n", [diff(Now, LastNow)]), + loop(Now); + {Pid, stop, Now} -> + io:format("\t(+~6.2fs)\n", [diff(Now, LastNow)]), + Pid ! ok + end. + +-spec start_stamp(string()) -> ok. + +start_stamp(Msg) -> + ?MODULE ! {stamp, Msg, now()}, + ok. + +-spec end_stamp() -> ok. + +end_stamp() -> + ?MODULE ! {stamp, now()}, + ok. + +-spec stop() -> ok. + +stop() -> + ?MODULE ! {self(), stop, now()}, + receive ok -> ok end. + +diff(T2, T1) -> + timer:now_diff(T2,T1) / 1000000. diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index 20911aaf8c..0d72014427 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -83,6 +83,7 @@ start() -> {Args, Analysis} = process_cl_args(), %% io:format("Args: ~p\n", [Args]), %% io:format("Analysis: ~p\n", [Analysis]), + 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), @@ -91,6 +92,7 @@ start() -> Analysis4 = collect_info(Analysis3), %% io:format("Final: ~p\n", [Analysis4#analysis.fms]), TypeInfo = get_type_info(Analysis4), + dialyzer_timing:stop(), show_or_annotate(TypeInfo), %% io:format("\nTyper analysis finished\n"), erlang:halt(0). -- cgit v1.2.3