Fix a bunch of deviations from our coding standards.

Estimated hours taken: 1
Branches: main

profiler/*.m:
	Fix a bunch of deviations from our coding standards.

	Rename some predicates to make them better reflect the predicates'
	semantics.
This commit is contained in:
Zoltan Somogyi
2006-11-10 03:26:28 +00:00
parent e65ee0f43f
commit ff386022ae
15 changed files with 395 additions and 397 deletions

View File

@@ -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.
%
%-----------------------------------------------------------------------------%

View File

@@ -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

View File

@@ -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,

View File

@@ -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)
).

View File

@@ -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.

View File

@@ -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)).

View File

@@ -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)
).

View File

@@ -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.
%
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%

View File

@@ -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("<spontaneous>\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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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").
%-----------------------------------------------------------------------------%

View File

@@ -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 <cycle X>.
%
:- 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))

View File

@@ -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")
)
)
;