[m-rev.] for review: improvements to deep profiler

Julien Fischer juliensf at cs.mu.OZ.AU
Tue Aug 23 23:29:17 AEST 2005


For review by anyone.

Estimated hours taken: 3
Branches: main, release

Improvements to the deep profiling tool.

Provide the facility to hide modules/procedures to which there
have been no calls.  This reduces the amount of clutter
when exploring the program module by module and when listing
the procedures in a module (the clutter is primarily a result
of unused standard library modules).  By default, we currently
do not hide any modules/procedures.

Add a toggle to sort lists of procedures by the number of redos
they perform.  We have had control at the head of tables to do
this for a while now.

Delete the function int_list_from_to/2 since that functionality
is now available in the standard library.

deep_profiler/html_format.m:
	Provide toggles that allow the user to show/hide inactive
	modules and procedures.

	Add a toggle to sort lists of procedures by the number
	of redos.

	Rename a numbered sequence of variables so that it
	is easier to insert new ones in the middle of the
	sequence.

deep_profiler/interface.m:
	Add support for hiding/showing inactive modules.

deep_profiler/measurements.m:
	Add a predicate, is_inactive/1, that test if an own_prof_info
	for a given entity is inactive.

deep_profiler/query.m:
	When generating the module and procedure summaries, respect
	the new preference settings for hiding/showing inactive
	modules/procedures.

deep_profiler/top_procs.m:
	Delete int_list_from_to/2 and replace calls to it with
	'..' from the standard library.

Julien.

Index: html_format.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/html_format.m,v
retrieving revision 1.9
diff -u -r1.9 html_format.m
--- html_format.m	14 Jul 2005 08:51:34 -0000	1.9
+++ html_format.m	23 Aug 2005 13:24:14 -0000
@@ -300,6 +300,18 @@
 	;
 		BoxToggle = ""
 	),
+	( list__member(toggle_inactive_modules, RelevantToggles) ->
+		InactiveModuleToggle =
+			footer_inactive_modules_toggle(Cmd, Pref, Deep)
+	;
+		InactiveModuleToggle = ""
+	),
+	( list__member(toggle_inactive_procs, RelevantToggles) ->
+		InactiveProcsToggle =
+			footer_inactive_procs_toggle(Cmd, Pref, Deep)
+	;
+		InactiveProcsToggle = ""
+	),
 	AllToggles =
 		FieldToggle ++
 		AncestorToggle ++
@@ -308,7 +320,9 @@
 		ContourToggle ++
 		TimeFormatToggle ++
 		ColourToggle ++
-		BoxToggle.
+		BoxToggle ++
+		InactiveModuleToggle ++
+		InactiveProcsToggle.

 %-----------------------------------------------------------------------------%

@@ -320,7 +334,9 @@
 	;	toggle_summarize
 	;	toggle_order_criteria
 	;	toggle_contour
-	;	toggle_time_format.
+	;	toggle_time_format
+	;	toggle_inactive_modules
+	;	toggle_inactive_procs.

 :- func command_relevant_toggles(cmd) = list(toggle_kind).

@@ -341,10 +357,10 @@
 	toggle_contour, toggle_time_format].
 command_relevant_toggles(modules) =
 	[toggle_fields, toggle_box, toggle_colour, toggle_order_criteria,
-	toggle_time_format].
+	toggle_time_format, toggle_inactive_modules].
 command_relevant_toggles(module(_)) =
 	[toggle_fields, toggle_box, toggle_colour, toggle_order_criteria,
-	toggle_time_format].
+	toggle_time_format, toggle_inactive_procs].
 command_relevant_toggles(top_procs(_, _, _, _)) =
 	[toggle_fields, toggle_box, toggle_colour, toggle_time_format].
 command_relevant_toggles(proc_static(_)) = [].
@@ -765,65 +781,112 @@

 toggle_cost_criteria(CostKind, InclDesc, Scope, UpdateCriteria) = Toggles :-
 	( CostKind \= calls ->
-		Msg1 = "Sort by calls",
-		Toggle1 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgCalls = "Sort by calls",
+		ToggleCalls = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(calls, InclDesc, Scope)),
-			s(Msg1)])
+			s(MsgCalls)])
 	;
-		Toggle1 = ""
+		ToggleCalls = ""
+	),
+	( CostKind \= redos ->
+		MsgRedos = "Sort by redos",
+		ToggleRedos = string.format("<A HREF=""%s"">%s</A>\n",
+			[s(UpdateCriteria(redos, InclDesc, Scope)),
+			s(MsgRedos)])
+	;
+		ToggleRedos = ""
 	),
 	( CostKind \= time ->
-		Msg2 = "Sort by time",
-		Toggle2 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgTime = "Sort by time",
+		ToggleTime = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(time, InclDesc, Scope)),
-			s(Msg2)])
+			s(MsgTime)])
 	;
-		Toggle2 = ""
+		ToggleTime = ""
 	),
 	( CostKind \= allocs ->
-		Msg3 = "Sort by allocations",
-		Toggle3 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgAllocs = "Sort by allocations",
+		ToggleAllocs = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(allocs, InclDesc, Scope)),
-			s(Msg3)])
+			s(MsgAllocs)])
 	;
-		Toggle3 = ""
+		ToggleAllocs = ""
 	),
 	( CostKind \= words ->
-		Msg4 = "Sort by words",
-		Toggle4 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgWords = "Sort by words",
+		ToggleWords = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(words, InclDesc, Scope)),
-			s(Msg4)])
+			s(MsgWords)])
 	;
-		Toggle4 = ""
+		ToggleWords = ""
 	),
 	(
 		InclDesc = self,
-		Msg5 = "Include descendants",
-		Toggle5 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgDesc = "Include descendants",
+		ToggleDesc = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(CostKind, self_and_desc, Scope)),
-			s(Msg5)])
+			s(MsgDesc)])
 	;
 		InclDesc = self_and_desc,
-		Msg5 = "Exclude descendants",
-		Toggle5 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgDesc = "Exclude descendants",
+		ToggleDesc = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(CostKind, self, Scope)),
-			s(Msg5)])
+			s(MsgDesc)])
 	),
 	(
 		Scope = per_call,
-		Msg6 = "Count overall cost",
-		Toggle6 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgScope = "Count overall cost",
+		ToggleScope = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(CostKind, InclDesc, overall)),
-			s(Msg6)])
+			s(MsgScope)])
 	;
 		Scope = overall,
-		Msg6 = "Count per-call cost",
-		Toggle6 = string__format("<A HREF=""%s"">%s</A>\n",
+		MsgScope = "Count per-call cost",
+		ToggleScope = string__format("<A HREF=""%s"">%s</A>\n",
 			[s(UpdateCriteria(CostKind, InclDesc, per_call)),
-			s(Msg6)])
+			s(MsgScope)])
+	),
+	Toggles = ToggleCalls ++ ToggleRedos ++ ToggleTime ++ ToggleAllocs
+		++ ToggleWords ++ ToggleDesc ++ ToggleScope.
+
+%-----------------------------------------------------------------------------%
+%
+% Toggles to control showing/hiding inactive modules/procedures
+%
+
+:- func footer_inactive_modules_toggle(cmd, preferences, deep) = string.
+
+footer_inactive_modules_toggle(Cmd, Pref0, Deep) = HTML :-
+	Pref0 ^ pref_inactive = inactive_items(Procs, Modules),
+	(
+		Modules = show,
+		Msg  = "Hide inactive modules",
+		Pref = Pref0 ^ pref_inactive := inactive_items(Procs, hide)
+	;
+		Modules = hide,
+		Msg  = "Show inactive modules",
+		Pref = Pref0 ^ pref_inactive := inactive_items(Procs, show)
+	),
+	HTML = string__format("<A HREF=""%s"">%s</A>\n",
+			[s(deep_cmd_pref_to_url(Pref, Deep, Cmd)),
+			s(Msg)]).
+
+:- func footer_inactive_procs_toggle(cmd, preferences, deep) = string.
+
+footer_inactive_procs_toggle(Cmd, Pref0, Deep) = HTML :-
+	Pref0 ^ pref_inactive = inactive_items(Procs, Modules),
+	(
+		Procs = show,
+		Msg = "Hide inactive procedures",
+		Pref = Pref0 ^ pref_inactive := inactive_items(hide, Modules)
+	;
+		Procs = hide,
+		Msg = "Show inactive procedures",
+		Pref = Pref0 ^ pref_inactive := inactive_items(show, Modules)
 	),
-	Toggles = Toggle1 ++ Toggle2 ++ Toggle3 ++ Toggle4
-		++ Toggle5 ++ Toggle6.
+	HTML = string__format("<A HREF=""%s"">%s</A>\n",
+			[s(deep_cmd_pref_to_url(Pref, Deep, Cmd)),
+			s(Msg)]).

 %-----------------------------------------------------------------------------%

Index: interface.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/interface.m,v
retrieving revision 1.9
diff -u -r1.9 interface.m
--- interface.m	14 Jul 2005 08:51:34 -0000	1.9
+++ interface.m	23 Aug 2005 13:24:17 -0000
@@ -176,7 +176,11 @@
 			pref_contour	:: contour,
 					% whether contour exclusion should be
 					% applied
-			pref_time	:: time_format
+			pref_time	:: time_format,
+
+			pref_inactive   :: inactive_items
+					% Whether we should show modules/procs
+					% that haven't been called.
 		).

 :- type port_fields
@@ -247,6 +251,14 @@
 	;	scale_by_millions
 	;	scale_by_thousands.

+:- type inactive_status ---> hide ; show.
+
+:- type inactive_items
+	---> inactive_items(
+		inactive_procs   :: inactive_status,
+		inactive_modules :: inactive_status
+	).
+
 :- func default_preferences = preferences.

 :- func default_fields = fields.
@@ -261,6 +273,7 @@
 :- func default_scope = measurement_scope.
 :- func default_contour = contour.
 :- func default_time_format = time_format.
+:- func default_inactive_items = inactive_items.

 :- func query_separator_char = char.
 :- func machine_datafile_cmd_pref_to_url(string, string, cmd, preferences)
@@ -291,7 +304,8 @@
 		default_summarize,
 		default_order_criteria,
 		default_contour,
-		default_time_format
+		default_time_format,
+		default_inactive_items
 	).

 default_fields = fields(port, ticks, no_alloc, memory(words)).
@@ -306,6 +320,7 @@
 default_scope = overall.
 default_contour = no_contour.
 default_time_format = scale_by_thousands.
+default_inactive_items = inactive_items(show, show).

 %-----------------------------------------------------------------------------%

@@ -577,7 +592,7 @@

 preferences_to_string(Pref) = PrefStr :-
 	Pref = preferences(Fields, Box, Colour, MaybeAncestorLimit,
-		Summarize, Order, Contour, Time),
+		Summarize, Order, Contour, Time, InactiveItems),
 	(
 		MaybeAncestorLimit = yes(AncestorLimit),
 		MaybeAncestorLimitStr =
@@ -586,7 +601,7 @@
 		MaybeAncestorLimit = no,
 		MaybeAncestorLimitStr = "no"
 	),
-	PrefStr = string__format("%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s",
+	PrefStr = string__format("%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s",
 		[s(fields_to_string(Fields)),
 		c(pref_separator_char), s(box_to_string(Box)),
 		c(pref_separator_char), s(colour_scheme_to_string(Colour)),
@@ -594,7 +609,10 @@
 		c(pref_separator_char), s(summarize_to_string(Summarize)),
 		c(pref_separator_char), s(order_criteria_to_string(Order)),
 		c(pref_separator_char), s(contour_to_string(Contour)),
-		c(pref_separator_char), s(time_format_to_string(Time))]).
+		c(pref_separator_char), s(time_format_to_string(Time)),
+		c(pref_separator_char),
+		s(inactive_items_to_string(InactiveItems))
+	]).

 url_component_to_cmd(QueryString, DefaultCmd) = Cmd :-
 	MaybeCmd = url_component_to_maybe_cmd(QueryString),
@@ -702,7 +720,8 @@
 	split(QueryString, pref_separator_char, Pieces),
 	(
 		Pieces = [FieldsStr, BoxStr, ColourStr, MaybeAncestorLimitStr,
-			SummarizeStr, OrderStr, ContourStr, TimeStr],
+			SummarizeStr, OrderStr, ContourStr, TimeStr,
+			InactiveItemsStr],
 		string_to_fields(FieldsStr, Fields),
 		string_to_box(BoxStr, Box),
 		string_to_colour_scheme(ColourStr, Colour),
@@ -716,10 +735,12 @@
 		string_to_summarize(SummarizeStr, Summarize),
 		string_to_order_criteria(OrderStr, Order),
 		string_to_contour(ContourStr, Contour),
-		string_to_time_format(TimeStr, Time)
+		string_to_time_format(TimeStr, Time),
+		string_to_inactive_items(InactiveItemsStr, InactiveItems)
 	->
 		Preferences = preferences(Fields, Box, Colour,
-			MaybeAncestorLimit, Summarize, Order, Contour, Time),
+			MaybeAncestorLimit, Summarize, Order, Contour, Time,
+			InactiveItems),
 		MaybePreferences = yes(Preferences)
 	;
 		MaybePreferences = no
@@ -952,6 +973,20 @@
 string_to_time_format("no", no_scale).
 string_to_time_format("mi", scale_by_millions).
 string_to_time_format("th", scale_by_thousands).
+
+:- func inactive_items_to_string(inactive_items) = string.
+
+inactive_items_to_string(inactive_items(hide, hide)) = "hh".
+inactive_items_to_string(inactive_items(show, hide)) = "sh".
+inactive_items_to_string(inactive_items(hide, show)) = "hs".
+inactive_items_to_string(inactive_items(show, show)) = "ss".
+
+:- pred string_to_inactive_items(string::in, inactive_items::out) is semidet.
+
+string_to_inactive_items("hh", inactive_items(hide,  hide)).
+string_to_inactive_items("sh", inactive_items(show,  hide)).
+string_to_inactive_items("hs", inactive_items(hide,  show)).
+string_to_inactive_items("ss", inactive_items(show,  show)).

 :- pred string_to_colour_scheme(string::in, colour_scheme::out) is semidet.

Index: measurements.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/measurements.m,v
retrieving revision 1.6
diff -u -r1.6 measurements.m
--- measurements.m	23 Jun 2005 08:21:29 -0000	1.6
+++ measurements.m	23 Aug 2005 13:24:17 -0000
@@ -59,6 +59,12 @@

 :- func own_to_string(own_prof_info) = string.

+	% Tests if this profiling information represents an entity in the
+	% program that was inactive during the profiling run, e.g. a module
+	% or procedure that has had no calls made to it.
+	%
+:- pred is_inactive(own_prof_info::in) is semidet.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

@@ -72,7 +78,7 @@
 :- type own_prof_info
 	--->	all(int, int, int, int, int, int, int)
 			% exits, fails, redos, excps, quanta, allocs, words
-			% implicit calls = exits + fails - redos
+			% implicit calls = exits + fails + excps - redos
 	;	det(int, int, int, int)
 			% exits, quanta, allocs, words;
 			% implicit fails == redos == excps == 0
@@ -318,6 +324,11 @@
 	string__int_to_string(Exits) ++ ", " ++
 	string__int_to_string(Fails) ++
 	")".
+
+is_inactive(all(0, 0, 0, 0, _, _, _)).
+is_inactive(det(0, _, _, _)).
+is_inactive(fast_det(0, _, _)).
+is_inactive(fast_nomem_semi(0, 0)).

 %----------------------------------------------------------------------------%
 :- end_module measurements.
Index: query.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/query.m,v
retrieving revision 1.8
diff -u -r1.8 query.m
--- query.m	23 Jun 2005 08:21:29 -0000	1.8
+++ query.m	23 Aug 2005 13:24:20 -0000
@@ -598,7 +598,7 @@
 				ToggleCostHTML ++
 				page_footer(Cmd, Pref, Deep)
 		;
-			TopProcs = list__map(
+			TopProcs = list.filter_map(
 				lookup_proc_total_to_html(Pref, Deep, no, ""),
 				list__map(wrap_proc_static_ptr, TopPSIs)),
 			RankedTopProcs = add_ranks(TopProcs),
@@ -630,7 +630,7 @@
 modules_to_html(Pref, Deep) = HTML :-
 	map__to_assoc_list(Deep ^ module_data, ModulePairs0),
 	list__filter(not_mercury_runtime, ModulePairs0, ModulePairs),
-	ModuleLines = list__map(module_summary_to_html(Pref, Deep),
+	ModuleLines = list.filter_map(module_summary_to_html(Pref, Deep),
 		ModulePairs),
 	SortedModuleLines = sort_line_groups(Pref ^ pref_criteria,
 		ModuleLines),
@@ -648,18 +648,21 @@
 	ModuleName \= "Mercury runtime".

 :- func module_summary_to_html(preferences, deep, pair(string, module_data))
-	= one_id_line.
+	= one_id_line is semidet.

 module_summary_to_html(Pref, Deep, ModuleName - ModuleData) = LineGroup :-
-	Own = ModuleData ^ module_own,
-	Desc = ModuleData ^ module_desc,
-	HTML =
-		string__format("<TD><A HREF=""%s"">%s</A></TD>\n",
-			[s(deep_cmd_pref_to_url(Pref, Deep,
-				module(ModuleName))),
-			s(ModuleName)]),
-	LineGroup = line_group(ModuleName, 0, ModuleName, Own, Desc, HTML,
-		unit).
+	ModuleData = module_data(Own, Desc, _),
+	( Pref ^ pref_inactive = inactive_items(_, hide), is_inactive(Own) ->
+		fail
+	;
+		HTML =
+			string__format("<TD><A HREF=""%s"">%s</A></TD>\n",
+				[s(deep_cmd_pref_to_url(Pref, Deep,
+					module(ModuleName))),
+				s(ModuleName)]),
+		LineGroup = line_group(ModuleName, 0, ModuleName, Own, Desc,
+			HTML, unit)
+	).

 %-----------------------------------------------------------------------------%

@@ -668,8 +671,8 @@

 module_to_html(Pref, Deep, _ModuleName, ModuleData, IdHeaders, HTML) :-
 	ModuleData = module_data(_Own, _Desc, PSPtrs),
-	ProcLines = list__map(lookup_proc_total_to_html(Pref, Deep, yes, ""),
-		PSPtrs),
+	ProcLines = list.filter_map(
+		lookup_proc_total_to_html(Pref, Deep, yes, ""), PSPtrs),
 	Criteria = Pref ^ pref_criteria,
 	SortedProcLines = sort_line_groups(Criteria, ProcLines),
 	( Criteria = by_cost(_, _, _) ->
@@ -895,14 +898,24 @@

 %-----------------------------------------------------------------------------%

+	% Fails if the procedure is inactive and the preferences say to
+	% hide inactive procedures.
+	%
 :- func lookup_proc_total_to_html(preferences, deep, bool, string,
-	proc_static_ptr) = one_id_line.
+	proc_static_ptr) = one_id_line is semidet.

 lookup_proc_total_to_html(Pref, Deep, Bold, Prefix, PSPtr) = LineGroup :-
 	deep_lookup_ps_own(Deep, PSPtr, Own),
-	deep_lookup_ps_desc(Deep, PSPtr, Desc),
-	LineGroup = proc_total_to_html(Pref, Deep, Bold, Prefix,
-		PSPtr, Own, Desc).
+	(
+		Pref ^ pref_inactive = inactive_items(hide, _),
+		is_inactive(Own)
+	->
+		fail
+	;
+		deep_lookup_ps_desc(Deep, PSPtr, Desc),
+		LineGroup = proc_total_to_html(Pref, Deep, Bold, Prefix,
+			PSPtr, Own, Desc)
+	).

 :- func lookup_proc_total_to_two_id_line(preferences, deep, bool, string,
 	proc_static_ptr) = two_id_line.
Index: top_procs.m
===================================================================
RCS file: /home/mercury1/repository/mercury/deep_profiler/top_procs.m,v
retrieving revision 1.4
diff -u -r1.4 top_procs.m
--- top_procs.m	14 Jul 2005 08:51:34 -0000	1.4
+++ top_procs.m	23 Aug 2005 13:24:21 -0000
@@ -74,7 +74,7 @@
 		SortCompatible = yes,
 		ProcStatics = Deep ^ proc_statics,
 		array__max(ProcStatics, MaxProcStatic),
-		PSIs0 = int_list_from_to(1, MaxProcStatic),
+		PSIs0 = 1 .. MaxProcStatic,
 		deep_lookup_proc_dynamics(Deep, Deep ^ root, RootPD),
 		RootPD ^ pd_proc_static = proc_static_ptr(RootPSI),
 		list__filter(filter_top_procs(Deep, RootPSI, FilterPred),
@@ -115,15 +115,6 @@
 				MaybeTopPSIs = ok(TopPSIs)
 			)
 		)
-	).
-
-:- func int_list_from_to(int, int) = list(int).
-
-int_list_from_to(From, To) = List :-
-	( From > To ->
-		List = []
-	;
-		List = [From | int_list_from_to(From + 1, To)]
 	).

 %-----------------------------------------------------------------------------%

--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list