diff --git a/profiler/atsort_callgraph.m b/profiler/atsort_callgraph.m index d035648ec..3cf93a43d 100644 --- a/profiler/atsort_callgraph.m +++ b/profiler/atsort_callgraph.m @@ -6,12 +6,11 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% atsort_callgraph.m -% +% File: atsort_callgraph.m. % Main author: petdr. % % Takes a list of files which contains the callgraph of a Mercury module -% and approximately topologically sorts them to std out. +% and approximately topologically sorts them to standard output. % %-----------------------------------------------------------------------------% diff --git a/profiler/call_graph.m b/profiler/call_graph.m index 5490247e4..50c235d67 100644 --- a/profiler/call_graph.m +++ b/profiler/call_graph.m @@ -6,8 +6,7 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% call_graph.m -% +% File: call_graph.m % Main author: petdr. % % Responsible for building the static call graph. The dynamic call graph is @@ -27,7 +26,7 @@ %-----------------------------------------------------------------------------% -:- pred call_graph.main(list(string)::in, +:- pred build_call_graph(list(string)::in, relation(string)::in, relation(string)::out, io::di, io::uo) is det. %-----------------------------------------------------------------------------% @@ -42,10 +41,11 @@ :- import_module bool. :- import_module maybe. :- import_module require. +:- import_module svrelation. %-----------------------------------------------------------------------------% -call_graph.main(Args, !StaticCallGraph, !IO) :- +build_call_graph(Args, !StaticCallGraph, !IO) :- globals.io_lookup_bool_option(dynamic_cg, Dynamic, !IO), globals.io_lookup_bool_option(very_verbose, VeryVerbose, !IO), % @@ -61,6 +61,7 @@ call_graph.main(Args, !StaticCallGraph, !IO) :- ). % build_static_call_graph: + % % Builds the static call graph located in the *.prof files. % :- pred build_static_call_graph(list(string)::in, bool::in, @@ -70,6 +71,7 @@ build_static_call_graph(Files, VeryVerbose, !StaticCallGraph, !IO) :- list.foldl2(process_prof_file(VeryVerbose), Files, !StaticCallGraph, !IO). % process_prof_file: + % % Puts all the Caller and Callee label pairs from File into the % static call graph relation. % @@ -103,8 +105,7 @@ process_prof_file_2(!StaticCallGraph, !IO) :- read_label_name(CalleeLabel, !IO), relation.lookup_element(!.StaticCallGraph, CallerLabel, CallerKey), relation.lookup_element(!.StaticCallGraph, CalleeLabel, CalleeKey), - relation.add(!.StaticCallGraph, CallerKey, CalleeKey, - !:StaticCallGraph), + svrelation.add(CallerKey, CalleeKey, !StaticCallGraph), process_prof_file_2(!StaticCallGraph, !IO) ; true diff --git a/profiler/demangle.m b/profiler/demangle.m index 62323dcd5..29ce136bf 100644 --- a/profiler/demangle.m +++ b/profiler/demangle.m @@ -9,8 +9,7 @@ % File: demangle.m % Author: fjh % -% A mercury symbol demangler. -% This is used to convert symbol names back +% A Mercury symbol demangler. This is used to convert symbol names back % into a form that users can understand. % % BEWARE: the code here is duplicated in util/mdemangle.c, diff --git a/profiler/demangle_test.m b/profiler/demangle_test.m index 4ffc87a85..723b098f4 100644 --- a/profiler/demangle_test.m +++ b/profiler/demangle_test.m @@ -1,19 +1,16 @@ %-----------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %-----------------------------------------------------------------------------% -% % Copyright (C) 1997, 2005-2006 The University of Melbourne. % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. -% %-----------------------------------------------------------------------------% % % File: demangle_test.m % Author: fjh % -% Front-end to a mercury symbol demangler. -% This is used to convert error messages from the linker back -% into a form that users can understand. +% Front-end to a Mercury symbol demangler. This is used to convert error +% messages from the linker back into a form that users can understand. % % BEWARE: % The code here duplicates the functionality of util/mdemangle.c. @@ -41,18 +38,16 @@ main(!IO) :- io.command_line_arguments(Args, !IO), ( Args = [_ | _], - % - % invoke demangle/2 on each command line argument - % + + % Invoke demangle/2 on each command line argument. list.map(demangle, Args, DemangledArgs), io.write_list(DemangledArgs, "\n", io.write_string, !IO), io.nl(!IO) ; Args = [], - % - % copy stdin to stdout, calling demangle/2 for - % every valid C identifier in the input - % + + % Copy stdin to stdout, calling demangle/2 for every valid C identifier + % in the input. demangle_stdin([], !IO) ). diff --git a/profiler/generate_output.m b/profiler/generate_output.m index d6f54df0e..956cd22cc 100644 --- a/profiler/generate_output.m +++ b/profiler/generate_output.m @@ -6,8 +6,7 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% generate_output.m -% +% File: generate_output.m % Main author: petdr. % % Takes the prof structure and generates the output. @@ -30,7 +29,7 @@ %-----------------------------------------------------------------------------% -:- pred generate_output.main(prof::in, map(string, int)::out, output::out, +:- pred generate_prof_output(prof::in, map(string, int)::out, output::out, io::di, io::uo) is det. :- func checked_float_divide(float, float) = float. @@ -47,10 +46,11 @@ :- import_module list. :- import_module rbtree. :- import_module relation. +:- import_module svmap. %-----------------------------------------------------------------------------% - % rbtrees are used because they allow duplicate values to be stored. + % We use rbtrees because they allow duplicate values to be stored. % This means that we can then convert to a sorted list of names which % can be used to lookup the output_prof map when we actually output. :- type profiling @@ -71,7 +71,7 @@ %-----------------------------------------------------------------------------% -generate_output.main(Prof, IndexMap, Output, !IO) :- +generate_prof_output(Prof, IndexMap, Output, !IO) :- globals.io_lookup_bool_option(very_verbose, VeryVerbose, !IO), % Get intitial values of use. @@ -104,9 +104,10 @@ process_prof_node_list([PN | PNs], Prof, VeryVerbose, !OutputProf, !IO) :- process_prof_node(PN, Prof, !OutputProf), process_prof_node_list(PNs, Prof, VeryVerbose, !OutputProf, !IO). - % process_prof_node: - % This is the main function. It converts the prof_node - % structure to the output_prof structure. + % process_prof_node(ProfNode, Prof, !OutputProf): + % + % This is the main function. It converts the prof_node structure + % to the output_prof structure. % :- pred process_prof_node(prof_node::in, prof::in, profiling::in, profiling::out) is det. @@ -114,20 +115,20 @@ process_prof_node_list([PN | PNs], Prof, VeryVerbose, !OutputProf, !IO) :- process_prof_node(ProfNode, Prof, !OutputProf) :- prof_node_type(ProfNode, ProfNodeType), ( ProfNodeType = predicate -> - generate_output.single_predicate(ProfNode, Prof, !OutputProf) + generate_output_for_single_predicate(ProfNode, Prof, !OutputProf) ; true - % generate_output.cycle(ProfNode, Prof, OutputProf0, - % OutputProf) + % generate_output.cycle(ProfNode, Prof, OutputProf0, OutputProf) ). - % generate_output.cycle + % generate_output_for_cycle(ProfNode, Prof, !OutputProf): + % % XXX % -:- pred generate_output.cycle(prof_node::in, prof::in, +:- pred generate_output_for_cycle(prof_node::in, prof::in, profiling::in, profiling::out) is det. -generate_output.cycle(ProfNode, Prof, !OutputProf) :- +generate_output_for_cycle(ProfNode, Prof, !OutputProf) :- prof_get_entire(Prof, Scale, _Units, IntTotalCounts, _, _, _CycleMap), TotalCounts = float.float(IntTotalCounts), @@ -136,9 +137,8 @@ generate_output.cycle(ProfNode, Prof, !OutputProf) :- !.OutputProf = profiling(InfoMap0, CallTree0, FreeTree), - % Calculate proportion of time in current predicate and its - % descendents as a percentage. - % + % Calculate proportion of time in current predicate and its descendants + % as a percentage. InitialFloat = float.float(Initial), ( TotalCounts = 0.0 -> DescPercentage = 0.0 @@ -148,7 +148,7 @@ generate_output.cycle(ProfNode, Prof, !OutputProf) :- % Calculate the self time spent in the current predicate. % Calculate the descendant time, which is the time spent in the - % current predicate and its descendants + % current predicate and its descendants. SelfTime = InitialFloat * Scale, DescTime = (InitialFloat + Prop) * Scale, @@ -160,13 +160,14 @@ generate_output.cycle(ProfNode, Prof, !OutputProf) :- !:OutputProf = profiling(InfoMap, CallTree, FreeTree). - % generate_output.single_predicate: + % generate_output_for_single_predicate(ProfNode, Prof, !OutputProf): + % % Fills out the output_prof structure when pred is a single predicate. % -:- pred generate_output.single_predicate(prof_node::in, prof::in, +:- pred generate_output_for_single_predicate(prof_node::in, prof::in, profiling::in, profiling::out) is det. -generate_output.single_predicate(ProfNode, Prof, !OutputProf) :- +generate_output_for_single_predicate(ProfNode, Prof, !OutputProf) :- prof_get_entire(Prof, Scale, _Units, IntTotalCounts, _, _, CycleMap), TotalCounts = float.float(IntTotalCounts), @@ -185,7 +186,7 @@ generate_output.single_predicate(ProfNode, Prof, !OutputProf) :- Name = LabelName ++ construct_name(NameList), % Calculate proportion of time in current predicate and its - % descendents as a percentage. + % descendants as a percentage. % Calculate proportion of time in current predicate % as a percentage. InitialFloat = float.float(Initial), @@ -193,8 +194,7 @@ generate_output.single_predicate(ProfNode, Prof, !OutputProf) :- DescPercentage = 0.0, FlatPercentage = 0.0 ; - DescPercentage = (InitialFloat + Prop) / TotalCounts - * 100.0, + DescPercentage = (InitialFloat + Prop) / TotalCounts * 100.0, FlatPercentage = InitialFloat / TotalCounts * 100.0 ), @@ -210,16 +210,11 @@ generate_output.single_predicate(ProfNode, Prof, !OutputProf) :- process_prof_node_children(ChildList, CycleNum, CycleMap, Prof, OutputChildList, OutputCycleChildList), - OutputProfNode = output_prof( - Name, CycleNum, - DescPercentage, - FlatPercentage, SelfTime, - DescTime, TotalCalls, - SelfCalls, - OutputParentList, - OutputChildList, - OutputCycleParentList, - OutputCycleChildList + OutputProfNode = output_prof(Name, CycleNum, + DescPercentage, FlatPercentage, SelfTime, DescTime, + TotalCalls, SelfCalls, + OutputParentList, OutputChildList, + OutputCycleParentList, OutputCycleChildList ), map.det_insert(InfoMap0, LabelName, OutputProfNode, InfoMap), @@ -233,8 +228,9 @@ generate_output.single_predicate(ProfNode, Prof, !OutputProf) :- ). % construct_name: - % When more then one predicate maps to the same address. This predicate + % When more then one predicate maps to the same address, this predicate % will build a string of all the different names separated by 'or's. + % :- func construct_name(list(string)) = string. construct_name([]) = "". @@ -244,7 +240,8 @@ construct_name([Name | Names]) = NameStr :- string.append(NameStr1, NameStr0, NameStr). % process_prof_node_parents: - % generate the parents output structure. + % + % Generate the parents output structure. % :- pred process_prof_node_parents(list(pred_info)::in, float::in, float::in, int::in, int::in, cycle_map::in, list(parent)::out, list(parent)::out) @@ -258,10 +255,12 @@ process_prof_node_parents(Parents0, SelfTime, DescTime, TotalCalls0, CycleNum, process_prof_node_parents_2(Parents, SelfTime, DescTime, FltTotalCalls, CycleMap, OutputParentList). - % remove_cycle_members - % removes any members of the same cycle from the parent listing - % of a predicate. Then adjusts the total calls so as not to include - % that predicate. + % remove_cycle_members(PredInfos, CycleNum, CycleMap, !TotalCalls, List, + % OutputCycleParentList): + % + % Removes any members of the same cycle from the parent listing + % of a predicate. Then adjusts the total calls so as not to include + % that predicate. % :- pred remove_cycle_members(list(pred_info)::in, int::in, cycle_map::in, int::in, int::out, list(pred_info)::out, list(parent)::out) is det. @@ -309,10 +308,8 @@ process_prof_node_parents_3([PN | PNs], SelfTime, DescTime, TotalCalls, CycleMap, !Output) :- pred_info_get_entire(PN, LabelName, Calls), - ( - % if parent member of cycle - map.search(CycleMap, LabelName, ParentCycleNum0) - -> + % Check if the parent is a member of a cycle. + ( map.search(CycleMap, LabelName, ParentCycleNum0) -> ParentCycleNum = ParentCycleNum0 ; ParentCycleNum = 0 @@ -414,15 +411,16 @@ process_prof_node_children_2([PN | PNs], Prof, !Output) :- rbtree.insert_duplicate(!.Output, Calls, Child, !:Output), process_prof_node_children_2(PNs, Prof, !Output). - % assign_index_numbers: + % assign_index_numbers(IndexMap, RevList, List): + % % Reverses the output list so that the predicates which account for % most of the time come first, and then assigns index numbers. % :- pred assign_index_numbers(map(string, int)::out, list(string)::in, list(string)::out) is det. -assign_index_numbers(IndexMap, List0, List) :- - list.reverse(List0, List), +assign_index_numbers(IndexMap, RevList, List) :- + list.reverse(RevList, List), assign_index_numbers_2(List, 1, map.init, IndexMap). :- pred assign_index_numbers_2(list(string)::in, int::in, @@ -430,7 +428,7 @@ assign_index_numbers(IndexMap, List0, List) :- assign_index_numbers_2([], _, !IndexMap). assign_index_numbers_2([X0 | Xs0], N, !IndexMap) :- - map.det_insert(!.IndexMap, X0, N, !:IndexMap), + svmap.det_insert(X0, N, !IndexMap), assign_index_numbers_2(Xs0, N + 1, !IndexMap). :- func profiling_init = profiling. diff --git a/profiler/globals.m b/profiler/globals.m index a178e70e8..dbc34cf43 100644 --- a/profiler/globals.m +++ b/profiler/globals.m @@ -5,15 +5,15 @@ % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% - +% % File: globals.m. % Main author: fjh. - +% % This module exports the `globals' type and associated access predicates. % The globals type is used to collect together all the various data % that would be global variables in an imperative language. -% This global data is stored in the io. - +% This global data is stored in the io state. +% %-----------------------------------------------------------------------------% :- module globals. @@ -113,9 +113,9 @@ what_to_profile("real-time", real_time). :- type globals ---> globals( - what_to_profile :: what_to_profile, - option_table :: option_table - ). + what_to_profile :: what_to_profile, + option_table :: option_table + ). globals.init(Options, globals(user_plus_system_time, Options)). diff --git a/profiler/mercury_profile.m b/profiler/mercury_profile.m index 344da4ef7..87e6e0de3 100644 --- a/profiler/mercury_profile.m +++ b/profiler/mercury_profile.m @@ -9,15 +9,12 @@ % Mercury profiler % Main author: petdr. % -% Notes: -% Processes the Prof.* and the *.prof files to produce an output very -% similar to `gprof' +% Processes the Prof.* and the *.prof files to produce an output very similar +% to `gprof' % -% Based on the profiling scheme described in [1]. -% -% [1] Graham, Kessler and McKusick "Gprof: a call graph execution -% profiler". In Proceedings of the 1982 SIGPLAN Symposium -% on Compiler Construction, pages 120-126. +% Based on the profiling scheme described in the paper: Graham, Kessler and +% McKusick "Gprof: a call graph execution profiler", Proceedings of the 1982 +% SIGPLAN Symposium on Compiler Construction, pages 120-126. % %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -161,17 +158,17 @@ main_2(no, Args, !IO) :- globals.io_lookup_bool_option(verbose, Verbose, !IO), maybe_write_string(Verbose, "% Processing input files...", !IO), - process_file.main(Prof0, CallGraph0, !IO), + process_profiling_data_files(Prof0, CallGraph0, !IO), maybe_write_string(Verbose, " done\n", !IO), ( CallGraphOpt = yes, maybe_write_string(Verbose, "% Building call graph...", !IO), - call_graph.main(Args, CallGraph0, CallGraph, !IO), + build_call_graph(Args, CallGraph0, CallGraph, !IO), maybe_write_string(Verbose, " done\n", !IO), maybe_write_string(Verbose, "% Propagating counts...", !IO), - propagate.counts(CallGraph, Prof0, Prof, !IO), + propagate_counts(CallGraph, Prof0, Prof, !IO), maybe_write_string(Verbose, " done\n", !IO) ; CallGraphOpt = no, @@ -179,11 +176,11 @@ main_2(no, Args, !IO) :- ), maybe_write_string(Verbose, "% Generating output...", !IO), - generate_output.main(Prof, IndexMap, OutputProf, !IO), + generate_prof_output(Prof, IndexMap, OutputProf, !IO), maybe_write_string(Verbose, " done\n", !IO), io.set_output_stream(StdOut, _, !IO), - output.main(OutputProf, IndexMap, !IO), + output_profile(OutputProf, IndexMap, !IO), io.nl(!IO) ). diff --git a/profiler/options.m b/profiler/options.m index daf27f9a8..ad49678af 100644 --- a/profiler/options.m +++ b/profiler/options.m @@ -5,13 +5,13 @@ % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% - +% % File: options.m. % Main author: fjh. - -% This defines the stuff necessary so that getopt.m -% can parse the command-line options. - +% +% This defines the stuff necessary so that getopt.m can parse the command line +% options. +% %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% diff --git a/profiler/output.m b/profiler/output.m index 5042110fb..27fb48c18 100644 --- a/profiler/output.m +++ b/profiler/output.m @@ -6,11 +6,10 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% output.m -% +% File: output.m % Main author: petdr. % -% Prints out the output. +% Prints out the output of the profiler. % %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -27,7 +26,8 @@ %-----------------------------------------------------------------------------% -:- pred output.main(output::in, map(string, int)::in, io::di, io::uo) is det. +:- pred output_profile(output::in, map(string, int)::in, + io::di, io::uo) is det. %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -47,7 +47,7 @@ %-----------------------------------------------------------------------------% -output.main(Output, IndexMap, !IO) :- +output_profile(Output, IndexMap, !IO) :- globals.io_get_globals(Globals, !IO), globals.get_what_to_profile(Globals, WhatToProfile), what_to_profile(WhatToProfileString, WhatToProfile), @@ -243,11 +243,11 @@ output_formatted_prof_node(ProfNode, Index, IndexMap, !IO) :- io.format("%67s", [s("\n")], !IO) ; list.sort(CycleParentList, SortedCycleParentList), - output_formatted_cycle_parent_list(SortedCycleParentList, - IndexMap, !IO), + output_formatted_cycle_parent_list(SortedCycleParentList, IndexMap, + !IO), list.sort(ParentList, SortedParentList), - output_formatted_parent_list(SortedParentList, IndexMap, - TotalCalls, !IO) + output_formatted_parent_list(SortedParentList, IndexMap, TotalCalls, + !IO) ), @@ -297,12 +297,13 @@ output_formatted_parent_list([Parent | Parents], IndexMap, TotalCalls, !IO) :- Parent = parent(LabelName, CycleNum, Self, Descendant, Calls), Name = construct_name(LabelName, CycleNum), Index = IndexMap ^ det_elem(LabelName), - io.format("%20.2f %11.2f %7d/%-11d %s [%d]\n", [f(Self), - f(Descendant), i(Calls), i(TotalCalls), - s(Name), i(Index)], !IO), + io.format("%20.2f %11.2f %7d/%-11d %s [%d]\n", + [f(Self), f(Descendant), i(Calls), i(TotalCalls), s(Name), i(Index)], + !IO), output_formatted_parent_list(Parents, IndexMap, TotalCalls, !IO). - % output_formatted_cycle_child_list + % output_formatted_cycle_child_list: + % % Outputs the children of a procedure that are in the same cycle. % :- pred output_formatted_cycle_child_list(list(child)::in, @@ -318,6 +319,7 @@ output_formatted_cycle_child_list([Child | Childs], IndexMap, !IO) :- output_formatted_cycle_child_list(Childs, IndexMap, !IO). % output_formatted_child_list: + % % outputs the child list of the current procedure. % :- pred output_formatted_child_list(list(child)::in, map(string, int)::in, @@ -419,11 +421,8 @@ output.flat_profile([LabelName | LNs], CumTime0, InfoMap, IndexMap, !IO) :- string.int_to_string(Index, IndexStr0), string.append_list(["[", IndexStr0, "] "], IndexStr), io.format("%5.1f %10.2f %8.2f %8d %8.2f %8.2f %s %s\n", - [ f(Percentage), f(CumTime), - f(Self), i(Calls), - f(SelfMs), f(DescMs), - s(FullName), s(IndexStr) - ], + [f(Percentage), f(CumTime), f(Self), i(Calls), + f(SelfMs), f(DescMs), s(FullName), s(IndexStr)], !IO), output.flat_profile(LNs, CumTime, InfoMap, IndexMap, !IO). @@ -448,7 +447,8 @@ output_alphabet_listing_2([Name - Index | T], !IO) :- io.format("[%d]\t%-30s\n", [i(Index), s(Name)], !IO), output_alphabet_listing_2(T, !IO). - % output.construct_name + % output.construct_name: + % % Constructs an output name with an optional cycle number if required. % :- func construct_name(string, int) = string. diff --git a/profiler/output_prof_info.m b/profiler/output_prof_info.m index 450d2a68e..24221b0ec 100644 --- a/profiler/output_prof_info.m +++ b/profiler/output_prof_info.m @@ -6,11 +6,10 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% output_prof_info.m -% +% File: output_prof_info.m % Main author: petdr. % -% Declare the main data structures for mercury.profile and their access +% Declare the main data structures for the Mercury profiler and their access % predicates, the actual types are exported as well. This is because some % predicates need to access entire data structure. % XXX Should maybe changed at a later date. @@ -33,70 +32,72 @@ % XXX Needs to be explained more clearly. :- type output ---> output( - map(string, output_prof), % Map which contains all - % the info which is - % required to generate - % the output. - list(string), % list of label names - % used to lookup map. - % list sorted so that - % it is in the correct - % order for call. - list(string) % same except for flat - ). + % The map that contains all the info which is required + % to generate the output. + + map(string, output_prof), + + % List of label names used to lookup map. list sorted so that + % it is in the correct order for call. + list(string), + + % Same, except flat. + list(string) + ). :- type output_prof ---> output_prof( - string, % predicate name - int, % cycle number - float, % %time in current predicate and descendants - float, % %time in current predicate - float, % self: time spent in current predicate - float, % descendants: time spent in current predicate and - % descendants - int, % called: number of times predicate is called - % excluding self recursive calls - int, % number of times predicate calls itself. - list(parent), % parents of predicate - list(child), % children of predicate - list(parent), % parents and children who are - list(child) % members of the same cycle. - ) - ; - output_cycle_prof( - string, % predicate name - int, % cycle number - float, % %time in current predicate and descendants - float, % self: time spent in current predicate - float, % descendants: time spent in current predicate - % and descendants - int, % called: number of times predicate is called - % excluding self recursive calls - int, % number of times predicate calls itself. - list(parent), % parents of predicate - list(child) % children of predicate - ). + string, % predicate name + int, % cycle number + float, % %time in current predicate and descendants + float, % %time in current predicate + float, % self: time spent in current predicate + float, % descendants: time spent in current predicate + % and descendants + int, % called: number of times predicate is called + % excluding self recursive calls + int, % number of times predicate calls itself. + list(parent), % parents of predicate + list(child), % children of predicate + list(parent), % parents and children who are + list(child) % members of the same cycle. + ) + ; output_cycle_prof( + string, % predicate name + int, % cycle number + float, % %time in current predicate and descendants + float, % self: time spent in current predicate + float, % descendants: time spent in current predicate + % and descendants + int, % called: number of times predicate is called + % excluding self recursive calls + int, % number of times predicate calls itself. + list(parent), % parents of predicate + list(child) % children of predicate + ). :- type parent ---> parent( - string, % parent name - int, % cycle number - float, % the number of seconds of current predicate's - % self time which is due to calls from this parent. - float, % same as above for descendants - int % calls to current predicate - ). + string, % parent name + int, % cycle number + float, % the number of seconds of current predicate's + % self time which is due to calls from this + % parent. + float, % same as above for descendants + int % calls to current predicate + ). :- type child ---> child( - string, % child name - int, % cycle number - float, % the number of seconds of child's self time - % which is due to calls from the current predicate. - float, % same as above for descendants - int, % number of times child called - int % total calls of child - ). + string, % child name + int, % cycle number + float, % the number of seconds of child's self time + % which is due to calls from the current + % predicate. + float, % same as above for descendants + int, % number of times child called + int % total calls of child + ). %-----------------------------------------------------------------------------% :- end_module output_prof_info. diff --git a/profiler/process_file.m b/profiler/process_file.m index 8a1d66d83..dada7c074 100644 --- a/profiler/process_file.m +++ b/profiler/process_file.m @@ -6,8 +6,7 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% process_file.m -% +% File: process_file.m % Main author: petdr. % % Processs the files that contain the label declarations, label counts and @@ -27,8 +26,8 @@ %-----------------------------------------------------------------------------% -:- pred process_file.main(prof::out, relation(string)::out, io::di, io::uo) - is det. +:- pred process_profiling_data_files(prof::out, relation(string)::out, + io::di, io::uo) is det. %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -52,7 +51,7 @@ %-----------------------------------------------------------------------------% -process_file.main(Prof, DynamicCallGraph, !IO) :- +process_profiling_data_files(Prof, DynamicCallGraph, !IO) :- globals.io_lookup_bool_option(very_verbose, VVerbose, !IO), globals.io_lookup_string_option(declfile, DeclFile, !IO), globals.io_lookup_string_option(countfile, CountFile, !IO), @@ -103,13 +102,14 @@ process_file.main(Prof, DynamicCallGraph, !IO) :- %-----------------------------------------------------------------------------% - % process_addr_decl: + % process_addr_decl(AddrDeclMap, ProfNodeMap, !IO): + % % Reads in the Prof.Decl file. % Builds the addrdecl map which associates label names(key) % with label addresses. % Also builds the prof_node_map which associates label addresses - % with the prof_node structure. Initialises and inserts the - % label name into the structure at the same time. + % with the prof_node structure. Initialises and inserts the label name + % into the structure at the same time. % :- pred process_addr_decl(addrdecl::out, prof_node_map::out, io::di, io::uo) is det. @@ -154,9 +154,11 @@ process_addr_decl_2(!AddrDecl, !ProfNodeMap, !IO) :- %-----------------------------------------------------------------------------% - % process_addr: - % Reads in the Prof.Counts file and stores all the counts in the - % prof_node structure. Also sums the total counts at the same time. + % process_addr(!ProfNodeMap, WhatToProfile, Scale, Units, TotalCounts, + % !IO): + % + % Reads in the Prof.Counts file and stores all the counts in the prof_node + % structure. Also sums the total counts at the same time. % :- pred process_addr(prof_node_map::in, prof_node_map::out, what_to_profile::out, float::out, string::out, int::out, @@ -209,9 +211,8 @@ process_addr_2(!TotalCounts, !ProfNodeMap, !IO) :- svmap.set(LabelAddr, ProfNode, !ProfNodeMap), !:TotalCounts = !.TotalCounts + Count ; - io.format("\nWarning address " ++ - "%d not found! Ignoring address and " ++ - "continuing computation.\n", + io.format("\nWarning address %d not found! " ++ + "Ignoring address and continuing computation.\n", [i(LabelAddr)], !IO) ), process_addr_2(!TotalCounts, !ProfNodeMap, !IO) @@ -221,7 +222,8 @@ process_addr_2(!TotalCounts, !ProfNodeMap, !IO) :- %-----------------------------------------------------------------------------% - % process_addr_pair: + % process_addr_pair(!ProfNodeMap, !AddrDecl, DynamicCallGraph, !IO): + % % Reads in the Prof.CallPair file and stores the data in the relevant % lists of the prof_node structure. Also calculates the number of % times a predicate is called. @@ -259,19 +261,18 @@ process_addr_pair_2(Dynamic, !DynamicCallGraph, !ProfNodeMap, !AddrDecl, read_label_addr(CalleeAddr, !IO), read_int(Count, !IO), - % Get child and parent information + % Get child and parent information. lookup_addr(CallerAddr, CallerProfNode0, !AddrDecl, !ProfNodeMap), lookup_addr(CalleeAddr, CalleeProfNode0, !AddrDecl, !ProfNodeMap), prof_node_get_pred_name(CallerProfNode0, CallerName), prof_node_get_pred_name(CalleeProfNode0, CalleeName), - % Insert child information - + % Insert child information. prof_node_concat_to_child(CalleeName, Count, CallerProfNode0, CallerProfNode), svmap.set(CallerAddr, CallerProfNode, !ProfNodeMap), - % Update the total calls field if not self recursive + % Update the total calls field if not self recursive. ( CalleeAddr \= CallerAddr -> prof_node_get_total_calls(CalleeProfNode0, TotalCalls0), TotalCalls = TotalCalls0 + Count, @@ -283,7 +284,7 @@ process_addr_pair_2(Dynamic, !DynamicCallGraph, !ProfNodeMap, !AddrDecl, prof_node_set_self_calls(Count, CalleeProfNode0, CalleeProfNode) ), - % Insert parent information + % Insert parent information. svmap.set(CalleeAddr, CalleeProfNode, !ProfNodeMap), % Add edge to call graph if generating dynamic call graph. @@ -303,8 +304,9 @@ process_addr_pair_2(Dynamic, !DynamicCallGraph, !ProfNodeMap, !AddrDecl, %-----------------------------------------------------------------------------% - % process_library_callgraph: - % XXX + % process_library_callgraph(LibraryATSort, LibPredMap, !IO): + % + % XXX % :- pred process_library_callgraph(list(string)::out, map(string, unit)::out, io::di, io::uo) is det. diff --git a/profiler/prof_debug.m b/profiler/prof_debug.m index 713162675..fee807be5 100644 --- a/profiler/prof_debug.m +++ b/profiler/prof_debug.m @@ -6,10 +6,11 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% prof_debug.m: Debuging predicates for the mercury profiler -% +% File: prof_debug.m. % Main author: petdr. % +% Debugging predicates for the Mercury profiler. +% %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -23,6 +24,7 @@ :- import_module string. % output_cliques: + % % Used to check that the topological ordering is being done correctly. % :- pred output_cliques(list(set(string))::in, io::di, io::uo) is det. diff --git a/profiler/prof_info.m b/profiler/prof_info.m index 418e493ae..5efed6481 100644 --- a/profiler/prof_info.m +++ b/profiler/prof_info.m @@ -6,8 +6,7 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% prof_info.m - +% File: prof_info.m % Main author: petdr. % % Declare the main data structures for mercury.profile and their access @@ -28,16 +27,16 @@ %-----------------------------------------------------------------------------% % prof: Data structure which contains ALL the relevant info for use - % in generating the output. + % in generating the output. :- type prof. - % addrdecl = map(label_name, label_address) + % Maps label names to label addresses. :- type addrdecl == map(string, int). - % prof_node_map = map(label_address, prof_node) + % Maps label addresses to prof nodes. :- type prof_node_map == map(int, prof_node). - % cycle_map == map(predicate_name, cycle it is in). + % Maps predicate names to the cycle the predicate is in. :- type cycle_map == map(string, int). % prof_node: Contains all the info used for output, for a single pred. @@ -230,7 +229,7 @@ % address. ) ; cycle_node( - % A node which is built up with more then one predicate + % A node which is built up with more than one predicate % and is a cycle. cycle_name :: string, @@ -262,7 +261,8 @@ %-----------------------------------------------------------------------------% % get_prof_node: - % Gets the prof_node given a label name. + % + % Gets the prof_node given a label name. % get_prof_node(Pred, AddrMap, ProfNodeMap, ProfNode) :- map.lookup(AddrMap, Pred, Key), @@ -392,7 +392,7 @@ prof_node_concat_to_name_list(_, cycle_node(_, _, _, _, _, _, _), _) :- prof_node_concat_to_member(Name, Count, cycle_node(A, B, C, D, CList, F, G), cycle_node(A, B, C, D, [pred_info(Name,Count) | CList], F, G)). prof_node_concat_to_member(_, _, pred_node(_, _, _, _, _, _, _, _, _), _) :- - error("prof_node_concat_to_member: pred_node has no members\n"). + error("prof_node_concat_to_member: pred_node has no members\n"). %-----------------------------------------------------------------------------% diff --git a/profiler/propagate.m b/profiler/propagate.m index 575479ade..79fd01c7e 100644 --- a/profiler/propagate.m +++ b/profiler/propagate.m @@ -6,14 +6,14 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% propagate.m -% +% File: propagate.m % Main author: petdr. % % Propagates the counts around the call_graph. -% To do this it first identifies all the cycles in the call graph. -% Each cycle is treated as a new super-predicate. ie All time propagated into -% a cycle is shared between all it's members. +% +% To do this, it first identifies all the cycles in the call graph. +% Each cycle is treated as a new super-predicate, i.e. all time propagated +% into a cycle is shared between all its members. % Then using a topological sorting of the call graph, the time is propagated % from the leaves of all the call graph to the head. % @@ -30,7 +30,7 @@ %-----------------------------------------------------------------------------% -:- pred propagate.counts(relation(string)::in, prof::in, prof::out, +:- pred propagate_counts(relation(string)::in, prof::in, prof::out, io::di, io::uo) is det. %-----------------------------------------------------------------------------% @@ -49,155 +49,148 @@ :- import_module sparse_bitset. :- import_module string. :- import_module svmap. +:- import_module svmulti_map. %-----------------------------------------------------------------------------% -:- type cycle_info == - pair( - map(string, int), % predicate - cycle - multi_map(int, string) % cycle - list preds - ). +:- type pred_to_cycle_map == map(string, int). +:- type cycle_to_preds_map == multi_map(int, string). -propagate.counts(CallGraph, !Prof, !IO) :- +:- type cycle_info + ---> cycle_info( + pred_to_cycle_map :: pred_to_cycle_map, + cycle_to_preds_map :: cycle_to_preds_map + ). + +propagate_counts(CallGraph, !Prof, !IO) :- prof_get_addrdeclmap(!.Prof, AddrDeclMap), prof_get_profnodemap(!.Prof, ProfNodeMap0), - propagate.identify_cycles(CallGraph, ATSort, CycleInfo), - propagate.update_cycles(CycleInfo, AddrDeclMap, ProfNodeMap0, - ProfNodeMap1), + identify_cycles(CallGraph, ATSort, CycleInfo), + update_cycles(CycleInfo, AddrDeclMap, ProfNodeMap0, ProfNodeMap1), - propagate.counts_2(ATSort, CycleInfo, AddrDeclMap, ProfNodeMap1, - ProfNodeMap), + propagate_counts_2(ATSort, CycleInfo, AddrDeclMap, + ProfNodeMap1, ProfNodeMap), - prof_set_cyclemap(fst(CycleInfo), !Prof), + prof_set_cyclemap(CycleInfo ^ pred_to_cycle_map, !Prof), prof_set_profnodemap(ProfNodeMap, !Prof). %-----------------------------------------------------------------------------% - % propagate.identify_cycles: + % identify_cycles(Rel, ATSort, CycleInfo): + % % Identifies the cycles in the callgraph and places the members of each % cycle into a map which associates a unique int with each cycle and a % multimap which associates with each cycle number a list of preds. % Also approximate topologically sorts the call graph. % -:- pred propagate.identify_cycles(relation(string)::in, list(string)::out, +:- pred identify_cycles(relation(string)::in, list(string)::out, cycle_info::out) is det. -propagate.identify_cycles(Rel, ATSort, CycleInfo) :- +identify_cycles(Rel, ATSort, cycle_info(PredToCycleMap, CycleToPredsMap)) :- relation.dfsrev(Rel, DfsRev), relation.inverse(Rel, RelInv), - propagate.identify_cycles_2(DfsRev, 1, RelInv, sparse_bitset.init, - [], ATSort, cycle_info_init, CycleInfo). + identify_cycles_2(DfsRev, 1, RelInv, sparse_bitset.init, + [], ATSort, map.init, PredToCycleMap, multi_map.init, CycleToPredsMap). -:- pred propagate.identify_cycles_2(list(relation_key)::in, int::in, +:- pred identify_cycles_2(list(relation_key)::in, int::in, relation(string)::in, relation_key_set::in, - list(string)::in, list(string)::out, cycle_info::in, cycle_info::out) - is det. + list(string)::in, list(string)::out, + pred_to_cycle_map::in, pred_to_cycle_map::out, + cycle_to_preds_map::in, cycle_to_preds_map::out) is det. -propagate.identify_cycles_2([], _, _, _, !ATSort, !CycleInfo). -propagate.identify_cycles_2([X | Xs0], CycleNum0, RelInv, Visit0, !ATSort, - !CycleInfo) :- - % - % Do a DFS on R'. The nodes we can get to and have not +identify_cycles_2([], _, _, _, !ATSort, !PredToCycleMap, !CycleToPredsMap). +identify_cycles_2([Key | Keys0], CycleNum0, RelInv, Visit0, !ATSort, + !PredToCycleMap, !CycleToPredsMap) :- + % Do a depth-first search on R'. The nodes we can get to and have not % already visited before are one cycle in the call graph. - % - relation.dfsrev(RelInv, X, Visit0, Visit, DfsRev0), + + relation.dfsrev(RelInv, Key, Visit0, Visit, DfsRev0), list.map(relation.lookup_key(RelInv), DfsRev0, DfsRev), ( - ( - DfsRev = [_] - ; - DfsRev = [], % This case should never happen - error("propagate.identify_cycles_2: empty list\n") - ) - -> + DfsRev = [], + error("identify_cycles_2: empty list\n") + ; + DfsRev = [_], CycleNum = CycleNum0 ; + DfsRev = [_, _ | _], CycleNum = CycleNum0 + 1, - propagate.add_to_cycle_map(DfsRev, CycleNum, !CycleInfo) + add_to_cycle_map(DfsRev, CycleNum, !PredToCycleMap, !CycleToPredsMap) ), list.append(DfsRev, !ATSort), - % - % Delete all visited elements from Xs0 as they have already - % been identified as part of a cycle. - % - list.delete_elems(Xs0, DfsRev0, Xs), - propagate.identify_cycles_2(Xs, CycleNum, RelInv, Visit, !ATSort, - !CycleInfo). - % cycle_info_init: - % Initialise the cycle_info structure. + % Delete all visited elements from Keys0 as they have already been + % identified as part of a cycle. + list.delete_elems(Keys0, DfsRev0, Keys), + identify_cycles_2(Keys, CycleNum, RelInv, Visit, !ATSort, + !PredToCycleMap, !CycleToPredsMap). + + % add_to_cycle_map(Preds, CycleNum, !PredToCycleMap, !CycleToPredsMap): % -:- func cycle_info_init = cycle_info. - -cycle_info_init = map.init - multi_map.init. - - % propagate.add_to_cycle_map: % Add all the predicates in a cycle into the cycle map. % -:- pred propagate.add_to_cycle_map(list(string)::in, int::in, - cycle_info::in, cycle_info::out) is det. +:- pred add_to_cycle_map(list(string)::in, int::in, + pred_to_cycle_map::in, pred_to_cycle_map::out, + cycle_to_preds_map::in, cycle_to_preds_map::out) is det. -propagate.add_to_cycle_map([], _, !CycleInfo). -propagate.add_to_cycle_map([X | Xs], V, M0 - MM0, M - MM) :- - map.det_insert(M0, X, V, M1), - multi_map.set(MM0, V, X, MM1), - propagate.add_to_cycle_map(Xs, V, M1 - MM1, M - MM). +add_to_cycle_map([], _, !PredToCycleMap, !CycleToPredsMap). +add_to_cycle_map([Pred | Preds], Cycle, !PredToCycleMap, !CycleToPredsMap) :- + svmap.det_insert(Pred, Cycle, !PredToCycleMap), + svmulti_map.set(Cycle, Pred, !CycleToPredsMap), + add_to_cycle_map(Preds, Cycle, !PredToCycleMap, !CycleToPredsMap). %-----------------------------------------------------------------------------% -:- pred propagate.update_cycles(cycle_info::in, addrdecl::in, +:- pred update_cycles(cycle_info::in, addrdecl::in, prof_node_map::in, prof_node_map::out) is det. -propagate.update_cycles(_M - MM, AddrDecl, !ProfNodeMap) :- - AssocList = multi_map.to_assoc_list(MM), - propagate.update_cycles_2(AssocList, AddrDecl, !ProfNodeMap). +update_cycles(CycleInfo, AddrDecl, !ProfNodeMap) :- + AssocList = multi_map.to_assoc_list(CycleInfo ^ cycle_to_preds_map), + update_cycles_2(AssocList, AddrDecl, !ProfNodeMap). -:- pred propagate.update_cycles_2(assoc_list(int, list(string))::in, +:- pred update_cycles_2(assoc_list(int, list(string))::in, addrdecl::in, prof_node_map::in, prof_node_map::out) is det. -propagate.update_cycles_2([], _, !ProfNodeMap). -propagate.update_cycles_2([ Num - Preds | Rest], AddrDecl, !ProfNodeMap) :- - propagate.update_cycles_3(Preds, Num, AddrDecl, !ProfNodeMap), - propagate.update_cycles_2(Rest, AddrDecl, !ProfNodeMap). +update_cycles_2([], _, !ProfNodeMap). +update_cycles_2([ Num - Preds | Rest], AddrDecl, !ProfNodeMap) :- + update_cycles_3(Preds, Num, AddrDecl, !ProfNodeMap), + update_cycles_2(Rest, AddrDecl, !ProfNodeMap). -:- pred propagate.update_cycles_3(list(string)::in, int::in, addrdecl::in, +:- pred update_cycles_3(list(string)::in, int::in, addrdecl::in, prof_node_map::in, prof_node_map::out) is det. -propagate.update_cycles_3([], _, _, !ProfNodeMap). -propagate.update_cycles_3([P | Ps], CycleNum, AddrDecl, !ProfNodeMap) :- +update_cycles_3([], _, _, !ProfNodeMap). +update_cycles_3([P | Ps], CycleNum, AddrDecl, !ProfNodeMap) :- get_prof_node(P, AddrDecl, !.ProfNodeMap, ProfNode0), prof_node_set_cycle_num(CycleNum, ProfNode0, ProfNode), update_prof_node(P, ProfNode, AddrDecl, !ProfNodeMap), - propagate.update_cycles_3(Ps, CycleNum, AddrDecl, !ProfNodeMap). + update_cycles_3(Ps, CycleNum, AddrDecl, !ProfNodeMap). %-----------------------------------------------------------------------------% - % propagate.counts_2 - % XXX + % propagate_counts_2 % -:- pred propagate.counts_2(list(string)::in, cycle_info::in, addrdecl::in, + % XXX + % +:- pred propagate_counts_2(list(string)::in, cycle_info::in, addrdecl::in, prof_node_map::in, prof_node_map::out) is det. -propagate.counts_2([], _, _, !ProfNodeMap). -propagate.counts_2([Pred | Preds], M - MM, AddrDeclMap, !ProfNodeMap) :- - ( map.search(M, Pred, Cycle) -> - multi_map.lookup(MM, Cycle, CyclePreds), +propagate_counts_2([], _, _, !ProfNodeMap). +propagate_counts_2([Pred | Preds], CycleInfo, AddrDeclMap, !ProfNodeMap) :- + ( map.search(CycleInfo ^ pred_to_cycle_map, Pred, Cycle) -> + multi_map.lookup(CycleInfo ^ cycle_to_preds_map, Cycle, CyclePreds), list.length(CyclePreds, Length), - ( - % Throw away the rest of the predicates to - % be processed by the profiler as we are about - % to make them into one cycle. - list.drop((Length - 1), Preds, NewPreds) - -> - propagate.process_cycle(CyclePreds, Cycle, AddrDeclMap, - !ProfNodeMap), - propagate.counts_2(NewPreds, M-MM, AddrDeclMap, !ProfNodeMap) + % Throw away the rest of the predicates to be processed by the profiler + % as we are about to make them into one cycle. + ( list.drop((Length - 1), Preds, NewPreds) -> + process_cycle(CyclePreds, Cycle, AddrDeclMap, !ProfNodeMap), + propagate_counts_2(NewPreds, CycleInfo, AddrDeclMap, !ProfNodeMap) ; - error("propagate.counts_2: list_drop failed\n") + error("propagate_counts_2: list_drop failed\n") ) ; get_prof_node(Pred, AddrDeclMap, !.ProfNodeMap, ProfNode), @@ -208,148 +201,155 @@ propagate.counts_2([Pred | Preds], M - MM, AddrDeclMap, !ProfNodeMap) :- TotalCounts = float(InitCounts) + PropCounts, - propagate.counts_3(ParentList, TotalCounts, float(TotalCalls), + propagate_counts_3(ParentList, TotalCounts, float(TotalCalls), AddrDeclMap, !ProfNodeMap), - propagate.counts_2(Preds, M-MM, AddrDeclMap, !ProfNodeMap) + propagate_counts_2(Preds, CycleInfo, AddrDeclMap, !ProfNodeMap) ). - % propagate.process_cycle: + % process_cycle(Preds, Cycle, AddrMap, !ProfNodeMap): + % % Takes the list of cycle preds and treats them as one single unit % called . % -:- pred propagate.process_cycle(list(string)::in, int::in, addrdecl::in, +:- pred process_cycle(list(string)::in, int::in, addrdecl::in, prof_node_map::in, prof_node_map::out) is det. -propagate.process_cycle(Preds, Cycle, AddrMap, !ProfNodeMap) :- - % - % Determine the parents of a cycle - % - propagate.cycle_parents(Preds, AddrMap, !.ProfNodeMap, Total, - Recursive, ParentList), - % - % Build the cycle name. - % - NameStr = string.format("< cycle %d as a whole >", [i(Cycle)]), - % - % Work out number of selfcounts. - % - SelfCounts = propagate.sum_self_counts(Preds, AddrMap, !.ProfNodeMap), - % - % Work out number of propagated counts. - % - PropCounts = propagate.sum_propagated_counts(Preds, AddrMap, - !.ProfNodeMap), +process_cycle(Preds, Cycle, AddrMap, !ProfNodeMap) :- + % Determine the parents of a cycle. + cycle_parents(Preds, AddrMap, !.ProfNodeMap, Total, Recursive, ParentList), - propagate.build_cycle_list(Preds, AddrMap, !.ProfNodeMap, CycleList), + % Build the cycle name. + NameStr = string.format("< cycle %d as a whole >", [i(Cycle)]), + + % Work out number of selfcounts. + SelfCounts = sum_self_counts(Preds, AddrMap, !.ProfNodeMap), + + % Work out number of propagated counts. + PropCounts = sum_propagated_counts(Preds, AddrMap, !.ProfNodeMap), + + build_cycle_list(Preds, AddrMap, !.ProfNodeMap, CycleList), ProfNode = prof_node_init_cycle(NameStr, 0, SelfCounts, PropCounts, CycleList, Total, Recursive), - % - % NB we give the address of a cycle as being the negative of - % the cycle number as this will be unique. - % + + % NB We give the address of a cycle as being the negative of the cycle + % number as this will be unique. Address = -Cycle, map.det_insert(!.ProfNodeMap, Address, ProfNode, !:ProfNodeMap), - % + % Propagate the counts XXX - % TotalCalls = float.float(Total), TotalCounts = float(SelfCounts) + PropCounts, - propagate.counts_3(ParentList, TotalCounts, TotalCalls, AddrMap, + propagate_counts_3(ParentList, TotalCounts, TotalCalls, AddrMap, !ProfNodeMap). - % propagate.sum_self_counts: + % sum_self_counts(Preds, ADMap, PNMap): + % % Sums the self counts fields for all the predicates. % -:- func propagate.sum_self_counts(list(string), addrdecl, prof_node_map) = int. +:- func sum_self_counts(list(string), addrdecl, prof_node_map) = int. -propagate.sum_self_counts(Preds, ADMap, PNMap) = - list.foldl((func(Pred, Sum0) = Sum :- - get_prof_node(Pred, ADMap, PNMap, ProfNode), - prof_node_get_initial_counts(ProfNode, InitCount), - Sum = Sum0 + InitCount - ), Preds, 0). +sum_self_counts(Preds, ADMap, PNMap) = Sum :- + list.foldl(accumulate_self_counts(ADMap, PNMap), Preds, 0, Sum). - % propagate.sum_propagated_counts: +:- pred accumulate_self_counts(addrdecl::in, prof_node_map::in, string::in, + int::in, int::out) is det. + +accumulate_self_counts(ADMap, PNMap, Pred, !Sum) :- + get_prof_node(Pred, ADMap, PNMap, ProfNode), + prof_node_get_initial_counts(ProfNode, InitCount), + !:Sum = !.Sum + InitCount. + + % sum_propagated_counts: + % % Sums the propagated counts fields for all the predicates. % -:- func propagate.sum_propagated_counts(list(string), addrdecl, prof_node_map) - = float. +:- func sum_propagated_counts(list(string), addrdecl, prof_node_map) = float. -propagate.sum_propagated_counts(Preds, ADMap, PNMap) = - list.foldl((func(Pred, Sum0) = Sum :- - get_prof_node(Pred, ADMap, PNMap, ProfNode), - prof_node_get_propagated_counts(ProfNode, PropCount), - Sum = Sum0 + PropCount - ), Preds, 0.0). +sum_propagated_counts(Preds, ADMap, PNMap) = Sum :- + list.foldl(accumulate_propagated_counts(ADMap, PNMap), Preds, 0.0, Sum). - % propagate.build_cycle_list +:- pred accumulate_propagated_counts(addrdecl::in, prof_node_map::in, + string::in, float::in, float::out) is det. + +accumulate_propagated_counts(ADMap, PNMap, Pred, !Sum) :- + get_prof_node(Pred, ADMap, PNMap, ProfNode), + prof_node_get_propagated_counts(ProfNode, PropCount), + !:Sum = !.Sum + PropCount. + + % build_cycle_list + % % Takes the list of predicates and works out how many times each - % predicate is called by a fellow predicate + % predicate is called by a fellow predicate. % XXX Not fully implemented yet. % -:- pred propagate.build_cycle_list(list(string)::in, addrdecl::in, - prof_node_map::in, list(pred_info)::out) is det. +:- pred build_cycle_list(list(string)::in, addrdecl::in, prof_node_map::in, + list(pred_info)::out) is det. -propagate.build_cycle_list([], _, _, []). -propagate.build_cycle_list([P | Ps], ADM, PNM, CycleList) :- - propagate.build_cycle_list(Ps, ADM, PNM, CycleList0), +build_cycle_list([], _, _, []). +build_cycle_list([P | Ps], ADM, PNM, CycleList) :- + build_cycle_list(Ps, ADM, PNM, CycleList0), pred_info_init(P, 0, PredInfo), - CycleList = [ PredInfo | CycleList0]. + CycleList = [PredInfo | CycleList0]. -:- pred propagate.counts_3(list(pred_info)::in, float::in, float::in, +:- pred propagate_counts_3(list(pred_info)::in, float::in, float::in, addrdecl::in, prof_node_map::in, prof_node_map::out) is det. -propagate.counts_3([], _, _, _, !ProfNodeMap). -propagate.counts_3([ P | Ps], TotalCounts, TotalCalls, AddrMap, - !ProfNodeMap) :- +propagate_counts_3([], _, _, _, !ProfNodeMap). +propagate_counts_3([ P | Ps], TotalCounts, TotalCalls, AddrMap, !ProfNodeMap) :- pred_info_get_entire(P, Pred, Calls), - % + % Work out the number of counts to propagate. - % XXX Probably need to do a 0.0 check - % + % XXX Probably need to do a 0.0 check. ToPropagateCounts = float(Calls) / TotalCalls * TotalCounts, - % + % Add new counts to current propagated counts. - % get_prof_node(Pred, AddrMap, !.ProfNodeMap, ProfNode0), prof_node_get_propagated_counts(ProfNode0, PropCount0), PropCount = PropCount0 + ToPropagateCounts, prof_node_set_propagated_counts(PropCount, ProfNode0, ProfNode), update_prof_node(Pred, ProfNode, AddrMap, !ProfNodeMap), - propagate.counts_3(Ps, TotalCounts, TotalCalls, AddrMap, !ProfNodeMap). + propagate_counts_3(Ps, TotalCounts, TotalCalls, AddrMap, !ProfNodeMap). - % propagate.cycle_parents + % cycle_parents(Preds, AddrMap, ProfNodeMap, TotalCalls, SelfCalls, + % ParentList): + % % Returns a list(pred_info) which is the list of parents of the cycle % Also returns how may times the cycle is called and how may times % predicates in a cycle call each other. % -:- pred propagate.cycle_parents(list(string)::in, addrdecl::in, - prof_node_map::in, int::out, int::out, list(pred_info)::out) is det. +:- pred cycle_parents(list(string)::in, addrdecl::in, prof_node_map::in, + int::out, int::out, list(pred_info)::out) is det. -propagate.cycle_parents(Preds, AddrMap, ProfNodeMap, TotalCalls, SelfCalls, +cycle_parents(Preds, AddrMap, ProfNodeMap, TotalCalls, SelfCalls, ParentList) :- - propagate.build_parent_map(Preds, AddrMap, ProfNodeMap, TotalCalls, + build_parent_map(Preds, AddrMap, ProfNodeMap, TotalCalls, SelfCalls, ParentMap), map.to_assoc_list(ParentMap, ParentAssocList), ParentList = assoc_list_to_pred_info_list(ParentAssocList). - % propagate.build_parent_map: + % build_parent_map(CliqueList, AddrMap, ProfNodeMap, TotalCalls, SelfCalls, + % ParentMap): + % % Builds a map which contains all the parents of a cycle, and the % total number of times that parent is called. Doesn't include the % cycle members, and callers which never call any of the members of % the cycle. At the same time also sums the total calls into the % cycle and the calls internal to the cycle. % -:- pred propagate.build_parent_map(list(string)::in, addrdecl::in, +:- pred build_parent_map(list(string)::in, addrdecl::in, prof_node_map::in, int::out, int::out, map(string, int)::out) is det. -propagate.build_parent_map([], _AddrMap, _ProfNodeMap, _, _, _ParentMap) :- - error("build_parent_map: empty cycle list\n"). -propagate.build_parent_map([C | Cs], AddrMap, ProfNodeMap, TotalCalls, - SelfCalls, ParentMap) :- - build_parent_map_2([C | Cs], [C | Cs], AddrMap, ProfNodeMap, - 0, TotalCalls, 0, SelfCalls, map.init, ParentMap). +build_parent_map(CliqueList, AddrMap, ProfNodeMap, TotalCalls, SelfCalls, + ParentMap) :- + ( + CliqueList = [], + error("build_parent_map: empty cycle list\n") + ; + CliqueList = [_ | _], + build_parent_map_2(CliqueList, CliqueList, AddrMap, ProfNodeMap, + 0, TotalCalls, 0, SelfCalls, map.init, ParentMap) + ). :- pred build_parent_map_2(list(string)::in, list(string)::in, addrdecl::in, prof_node_map::in, int::in, int::out, int::in, int::out, @@ -360,27 +360,30 @@ build_parent_map_2([C | Cs], CliqueList, AddrMap, ProfNodeMap, !TotalCalls, !SelfCalls, !ParentMap) :- get_prof_node(C, AddrMap, ProfNodeMap, ProfNode), prof_node_get_parent_list(ProfNode, ParentList), - add_to_parent_map(ParentList, CliqueList, 0, TotalCalls1, - 0, SelfCalls1, !ParentMap), + add_to_parent_map(ParentList, CliqueList, 0, TotalCalls1, 0, SelfCalls1, + !ParentMap), !:TotalCalls = !.TotalCalls + TotalCalls1, !:SelfCalls = !.SelfCalls + SelfCalls1, - build_parent_map_2(Cs, CliqueList, AddrMap, ProfNodeMap, !TotalCalls, - !SelfCalls, !ParentMap). + build_parent_map_2(Cs, CliqueList, AddrMap, ProfNodeMap, + !TotalCalls, !SelfCalls, !ParentMap). - % add_to_parent_map: - % Adds list of parents to parent map. Ignores clique members and - % repeats and callers which never call current predicate. - % Also returns the total number of times predicate is called. + % add_to_parent_map(Preds, CliqueList, !TotalCalls, !SelfCalls, + % !ParentMap): + % + % Adds list of parents to parent map. Ignores clique members and repeats + % and callers which never call current predicate. Also returns the total + % number of times predicate is called. % :- pred add_to_parent_map(list(pred_info)::in, list(string)::in, int::in, int::out, int::in, int::out, map(string, int)::in, map(string, int)::out) is det. add_to_parent_map([], _, !TotalCalls, !SelfCalls, !ParentMap). -add_to_parent_map([P | Ps], CliqueList, !TotalCalls, !SelfCalls, !ParentMap) :- - pred_info_get_pred_name(P, PredName), - pred_info_get_counts(P, Counts), +add_to_parent_map([Pred | Preds], CliqueList, !TotalCalls, !SelfCalls, + !ParentMap) :- + pred_info_get_pred_name(Pred, PredName), + pred_info_get_counts(Pred, Counts), ( ( list.member(PredName, CliqueList) @@ -389,18 +392,18 @@ add_to_parent_map([P | Ps], CliqueList, !TotalCalls, !SelfCalls, !ParentMap) :- ) -> !:SelfCalls = !.SelfCalls + Counts, - add_to_parent_map(Ps, CliqueList, !TotalCalls, !SelfCalls, !ParentMap) + add_to_parent_map(Preds, CliqueList, !TotalCalls, !SelfCalls, + !ParentMap) ; - ( - map.search(!.ParentMap, PredName, CurrCount0) - -> + ( map.search(!.ParentMap, PredName, CurrCount0) -> CurrCount = CurrCount0 + Counts, svmap.det_update(PredName, CurrCount, !ParentMap) ; svmap.det_insert(PredName, Counts, !ParentMap) ), !:TotalCalls = !.TotalCalls + Counts, - add_to_parent_map(Ps, CliqueList, !TotalCalls, !SelfCalls, !ParentMap) + add_to_parent_map(Preds, CliqueList, !TotalCalls, !SelfCalls, + !ParentMap) ). :- func assoc_list_to_pred_info_list(assoc_list(string, int)) diff --git a/profiler/read.m b/profiler/read.m index a05a5c2cd..5d10a61f5 100644 --- a/profiler/read.m +++ b/profiler/read.m @@ -6,10 +6,11 @@ % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % -% read.m: Input predicates for use with mercury_profile -% +% File: read.m. % Main author: petdr. % +% Input predicates for use with mercury_profile. +% %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -67,8 +68,8 @@ maybe_read_label_addr(MaybeLabelAddr, !IO) :- ( string.base_string_to_int(16, LabelAddrStr, LabelAddrHex) -> MaybeLabelAddr = yes(LabelAddrHex) ; - error("maybe_read_label_addr: Label " ++ - "address not hexadecimal or integer\n") + error("maybe_read_label_addr: " ++ + "Label address not hexadecimal or integer\n") ) ) ;