diff: memory profiling (round 2)

Fergus Henderson fjh at murlibobo.cs.mu.OZ.AU
Sat Dec 6 02:27:18 AEDT 1997


Hi,

Here's the diff with respect to the previous one.
This addresses the all stuff Zoltan raised in his review,
except for his comment about mprof's `--count-file' option.

The log message is the same except for the following addition:

	NEWS:
		Mention support for memory profiling.

I will commit this now.

--- old/mercury/NEWS	Mon Nov 24 02:04:57 1997
+++ NEWS	Fri Dec  5 13:58:30 1997
@@ -223,8 +223,11 @@
 
   See the "Using Prolog" section of the Mercury User's Guide for details.
 
-* The profiler now supports profiling just user time, or profiling
+* The Mercury profiler has a number of new features.
+
+  The profiler now supports profiling just user time, or profiling
   real (elapsed) time, rather than profiling user + system time.
+  We've also added support for memory profiling.
 
   See the "Profiling" chapter of the Mercury User's Guide for details.
 
--- old/mercury/compiler/handle_options.m	Sat Dec  6 01:59:26 1997
+++ compiler/handle_options.m	Fri Dec  5 13:59:18 1997
@@ -401,7 +401,7 @@
 		;
 			( ProfileMemory = yes ->
 				Part4 = ".profmemtime" /* not allowed */
-					/* `ml' which catch the error */
+					/* `ml' will catch the error */
 			; 
 				Part4 = ".proftime" /* currently useless */
 			)
@@ -416,7 +416,7 @@
 		; 
 			( ProfileMemory = yes ->
 				Part4 = ".profmem" /* not allowed */
-					/* `ml' which catch the error */
+					/* `ml' will catch the error */
 			; 
 				Part4 = ""
 			)
--- old/mercury/compiler/options.m	Sat Dec  6 01:59:27 1997
+++ compiler/options.m	Fri Dec  5 14:19:09 1997
@@ -109,9 +109,9 @@
 		;	gcc_global_registers
 		;	asm_labels
 		;	gc
-		;	profiling
-		;	time_profiling
-		;	memory_profiling
+		;	profiling		% profile_time + profile_calls
+		;	time_profiling		% profile_time + profile_calls
+		;	memory_profiling	% profime_mem + profile_calls
 		;	profile_calls
 		;	profile_time
 		;	profile_memory
--- old/mercury/doc/user_guide.texi	Sat Dec  6 01:59:28 1997
+++ doc/user_guide.texi	Fri Dec  5 14:27:37 1997
@@ -1336,7 +1336,7 @@
 To create the profile, you need to invoke @samp{mprof} with the
 @samp{-m} (@samp{--profile memory-words}) option.  This will profile
 the amount of memory allocated, measured in units of words. 
-(A word is 4 bytes on a 32-bit architecture, or 8 bytes on a 64-bit
+(A word is 4 bytes on a 32-bit architecture, and 8 bytes on a 64-bit
 architecture.)
 
 Alternatively, you can use @samp{mprof}'s @samp{-M}
--- old/mercury/library/benchmarking.m	Sat Dec  6 02:00:42 1997
+++ library/benchmarking.m	Fri Dec  5 23:09:53 1997
@@ -89,9 +89,9 @@
 
 #ifdef MEMORY_PROFILING
 
-  #define MEMORY_PROFILE_SIZE	10	/* Display this many top entries */
+  #define MEMORY_PROFILE_SIZE	10	/* Profile the top 10 entries */
 
-  #define MAX_REPORT_LINES	10	/* ?? */
+  #define MAX_REPORT_LINES	10	/* Display the top 10 entries */
 
   /* local types */
 
@@ -243,8 +243,7 @@
 	} else {
 		table_size = MR_memprof_type.num_entries;
 	}
-	table = (ML_memprof_report_entry *) prof_malloc(table_size
-		* sizeof(ML_memprof_report_entry));
+	table = make_many(ML_memprof_report_entry, table_size);
 
 	/*
 	** Print the by-procedure memory profile
@@ -275,7 +274,7 @@
 	/*
 	** Deallocate space for the table
 	*/
-	/* unfortunately prof_malloc doesn't let us free the table! */
+	oldmem(table);
 
 	/*
 	** Print the overall memory usage
@@ -286,6 +285,12 @@
 		ML_overall_counter.words_at_period_end
 	);
 
+/*
+** ML_update_counter(counter, float_counter):
+**	Copy the data for a period from `counter' into
+**	`float_counter' (changing the format slightly as we go),
+**	and update `counter' to reflect the start of a new period.
+*/
 static void
 ML_update_counter(MR_memprof_counter *counter,
 	ML_memprof_float_counter *float_counter)
@@ -313,59 +318,64 @@
 
 /*
 ** Insert an entry into the table of the top `table_size' entries.
-** Entries are ranked according to their cells_at_period_end.
-** (XXX Why? Why not according to words_at_period_end?).
+** Entries are ranked according to their words_at_period_end.
+** (This is an arbitrary choice; we might equally well choose
+** to order them by cells_at_period_end.  I prefer words.)
 ** Entries that are not in the top `table_size' are discarded.
 */
 static int
 ML_insert_into_table(const ML_memprof_report_entry *new_entry,
 	ML_memprof_report_entry *table, int table_size, int next_slot)
 {
-	if (new_entry->counter.cells_since_period_start <= 0.0) {
-		/* ignore such entries */
-	} else if (next_slot < table_size) {
-		/*
-		** XXX shouldn't we insert it in sorted order here,
-		** rather than just shoving it at the end of the table??
-		*/
-		table[next_slot] = *new_entry;
-		next_slot++;
-	} else {
-		bool	handled = FALSE;
-		int	i, j;
+	int slot;
 
-		for (i = table_size-1; i >= 0; i--) {
-			if (table[i].counter.cells_at_period_end >
-				new_entry->counter.cells_at_period_end)
-			{
-				if (i < table_size-1) {
-					/*
-					** New entry is smaller than
-					** all the entries in the table,
-					** so nothing needs to be done
-					*/
-				} else {
-					/* shift all later entries down  */
-					for (j = table_size-1; j > i; j--)
-						table[j] = table[j-1];
+	/* ignore entries whose counts are zero */
+	if (new_entry->counter.words_at_period_end <= 0.0) {
+		return next_slot;
+	}
 
-					table[i+1] = *new_entry;
-				}
+	/*
+	** Find the slot where this entry should be inserted.
+	** Start at the end and work backwards until we find
+	** the start of the table or until we find a table
+	** entry which ranks higher that the new entry.
+	*/
+	slot = next_slot;
+	while (slot > 0 && table[slot - 1].counter.words_at_period_end <
+				new_entry->counter.words_at_period_end)
+	{
+		slot--;
+	}
 
-				handled = TRUE;
-			}
+	/*
+	** If this entry fits in the table, then
+	** shuffle the displaced entries to the right,
+	** insert the new entry in the table, and increment next_slot
+	** (unless it is already at the end of the table).
+	*/
+	if (slot < table_size) {
+		int i;
+		for (i = table_size - 1; i >= slot; i--) {
+			table[i + 1] = table[i];
 		}
-		if (!handled) {
-			/* new entry must be bigger than all previous ones */
-			for (j = table_size-1; j > 0; j--)
-				table[j] = table[j-1];
 
-			table[0] = *new_entry;
+		table[slot] = *new_entry;
+
+		if (next_slot < table_size) {
+			next_slot++;
 		}
 	}
+
 	return next_slot;
 }
 
+/*
+** ML_memory_profile_top_table(node, table, table_size, next_slot):
+**	Insert the entries for `node' and its children into `table',
+**	which is big enough to hold the top `table_size' entries.
+**	`next_slot' specifies the number of entries currently
+**	in the table.  Returns the new value of `next_slot'.
+*/
 static int
 ML_memory_profile_top_table(MR_memprof_record *node,
 	ML_memprof_report_entry *table, int table_size, int next_slot)
@@ -387,6 +397,13 @@
 	return next_slot;
 }
 
+/*
+** ML_memory_profile_fill_table(node, table, next_slot):
+**	Insert the entries for `node' and its children into `table',
+**	which the caller guarantees is big enough to hold them all.
+**	`next_slot' specifies the number of entries currently
+**	in the table.  Returns the new value of `next_slot'.
+*/
 static int
 ML_memory_profile_fill_table(MR_memprof_record *node,
 	ML_memprof_report_entry *table, int next_slot)
@@ -405,6 +422,10 @@
 	return next_slot;
 }
 
+/*
+** ML_memory_profile_report(table, num_entries, complete):
+**	Print out a profiling report for the specified table.
+*/
 static void
 ML_memory_profile_report(const ML_memprof_table *table, int num_entries,
 	bool complete)
@@ -504,7 +525,7 @@
   #define	rep_count	r5
   #define	count_output	r1
   #define	soln_output	r1
-    #define	time_output	r2
+  #define	time_output	r2
 #else
   #define	rep_count	r6
   #define	count_output	r5
--- old/mercury/profiler/output.m	Sat Dec  6 02:01:09 1997
+++ profiler/output.m	Fri Dec  5 14:52:06 1997
@@ -313,7 +313,7 @@
 	
 
 % output_formatted_cycle_child_list
-%	outputs the childs of a procedure that are in the same cycle.
+%	outputs the children of a procedure that are in the same cycle.
 %
 :- pred output_formatted_cycle_child_list(list(child), map(string, int),
                                                         io__state, io__state).
--- old/mercury/profiler/process_file.m	Sat Dec  6 02:01:09 1997
+++ profiler/process_file.m	Fri Dec  5 14:53:07 1997
@@ -40,7 +40,7 @@
 
 
 process_file__main(Prof, DynamicCallGraph) -->
-        globals__io_lookup_bool_option(very_verbose, VVerbose),
+	globals__io_lookup_bool_option(very_verbose, VVerbose),
 	globals__io_lookup_string_option(declfile, DeclFile),
 	globals__io_lookup_string_option(countfile, CountFile),
 	globals__io_lookup_string_option(pairfile, PairFile),
@@ -48,29 +48,29 @@
 	globals__io_lookup_bool_option(dynamic_cg, Dynamic),
 
 	% process the decl file
-        maybe_write_string(VVerbose, "\n\t% Processing "),
+	maybe_write_string(VVerbose, "\n\t% Processing "),
 	maybe_write_string(VVerbose, DeclFile),
 	maybe_write_string(VVerbose, "..."),
-        process_addr_decl(AddrDeclMap, ProfNodeMap0),
-        maybe_write_string(VVerbose, " done.\n"),
+	process_addr_decl(AddrDeclMap, ProfNodeMap0),
+	maybe_write_string(VVerbose, " done.\n"),
 
 	% process the timing counts file
-        maybe_write_string(VVerbose, "\t% Processing "),
+	maybe_write_string(VVerbose, "\t% Processing "),
 	maybe_write_string(VVerbose, CountFile),
 	maybe_write_string(VVerbose, "..."),
-        process_addr(ProfNodeMap0, ProfNodeMap1, WhatToProfile, Scale, Units,
+	process_addr(ProfNodeMap0, ProfNodeMap1, WhatToProfile, Scale, Units,
 		TotalCounts),
-        maybe_write_string(VVerbose, " done.\n"),
+	maybe_write_string(VVerbose, " done.\n"),
 
 	% process the call pair counts file
-        maybe_write_string(VVerbose, "\t% Processing "),
+	maybe_write_string(VVerbose, "\t% Processing "),
 	maybe_write_string(VVerbose, PairFile),
 	maybe_write_string(VVerbose, "..."),
-        process_addr_pair(ProfNodeMap1, DynamicCallGraph, ProfNodeMap),
-        maybe_write_string(VVerbose, " done.\n"),
+	process_addr_pair(ProfNodeMap1, DynamicCallGraph, ProfNodeMap),
+	maybe_write_string(VVerbose, " done.\n"),
 
 	{ map__init(CycleMap) },
-        { prof_set_entire(Scale, Units, TotalCounts, AddrDeclMap, 
+	{ prof_set_entire(Scale, Units, TotalCounts, AddrDeclMap, 
 						ProfNodeMap, CycleMap, Prof) },
 	globals__io_get_globals(Globals0),
 	{ globals__set_what_to_profile(Globals0, WhatToProfile, Globals) },
@@ -117,7 +117,7 @@
 		io__seen
 	;
 		{ Result = error(Error) },
-                { io__error_message(Error, ErrorMsg) },
+		{ io__error_message(Error, ErrorMsg) },
 
 		{ string__append("error opening declaration file `", DeclFile, 
 					Str0) },
@@ -265,7 +265,7 @@
 		io__seen
 	;
 		{ Result = error(Error) },
-                { io__error_message(Error, ErrorMsg) },
+		{ io__error_message(Error, ErrorMsg) },
 		{ string__append("error opening pair file `", PairFile, 
 					Str0) },
 		{ string__append(Str0, "': ", Str1) },
@@ -359,10 +359,10 @@
 		io__seen
 	;
 		{ Result = error(Error) },
-                { io__error_message(Error, ErrorMsg) },
-                io__stderr_stream(StdErr),
-                io__write_strings(StdErr, ["mprof: error opening pair file `",
-                        LibFile, "': ", ErrorMsg, "\n"]),
+		{ io__error_message(Error, ErrorMsg) },
+		io__stderr_stream(StdErr),
+		io__write_strings(StdErr, ["mprof: error opening pair file `",
+			LibFile, "': ", ErrorMsg, "\n"]),
 		{ LibraryATSort = [] },
 		{ LibPredMap = LibPredMap0 }
 	).
--- old/mercury/runtime/Mmakefile	Sat Dec  6 02:03:10 1997
+++ runtime/Mmakefile	Sat Dec  6 02:04:38 1997
@@ -119,6 +119,7 @@
 
 DLL_CFLAGS	= -Dlibmer_DEFINE_DLL
 
+# the following header files are created automatically by Makefile.DLLs
 LIBMER_DLL_H	 = libmer_dll.h
 LIBMER_GLOBALS_H = libmer_globals.h
 
--- old/mercury/runtime/mercury_dummy.c	Sun Nov 23 18:21:19 1997
+++ runtime/mercury_dummy.c	Fri Dec  5 15:12:37 1997
@@ -5,7 +5,7 @@
 */
 
 #include "mercury_dummy.h"
-#include "mercury_imp.h"	/* we need libmer_globals.h for Windows DLLs */
+#include "mercury_imp.h"	/* we need libmer_dll.h for Windows DLLs */
 
 /*
 ** This dummy function is in a file of its own to ensure
--- old/mercury/runtime/mercury_imp.h	Wed Dec  3 18:26:17 1997
+++ runtime/mercury_imp.h	Fri Dec  5 23:02:37 1997
@@ -26,8 +26,9 @@
 #include	"mercury_conf.h"
 
 /*
-** The following must come before any definitions of global variables.
-** This is necessary to support DLLs on Windows.
+** The following must come before any declarations of or use of
+** global variables.  This is necessary to support DLLs on Windows.
+** Note: `libmer_dll.h' is automatically generated by `Makefile.DLLs'.
 */
 #ifdef USE_DLLS
   #include "libmer_dll.h"
--- old/mercury/runtime/mercury_label.c	Sat Dec  6 02:01:09 1997
+++ runtime/mercury_label.c	Fri Dec  5 23:02:37 1997
@@ -9,7 +9,7 @@
 ** that map from procedure names to addresses and vice versa.
 */
 
-#include	"mercury_imp.h"	/* we need libmer_globals.h for Windows DLLs */
+#include	"mercury_imp.h"	/* we need libmer_dll.h for Windows DLLs */
 
 #include	<stdio.h>
 #include	<string.h>



More information about the developers mailing list