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