[m-rev.] diff: Add profiling for memory zone usage.
Paul Bone
pbone at csse.unimelb.edu.au
Wed Nov 23 21:57:21 AEDT 2011
Add support for tracking the number, and amount of memory consumed by memory
zones. The current and maximum values are tracked. This support is only
compiled in if the MR_PROFILE_ZONES C macro is defined when building the
runtime system.
runtime/mercury_memory_zones.[ch]:
As above.
runtime/mercury_wrapper.c:
Print out the zone profiling data as the runtime is exiting.
util/mkinit.c:
Add support for measuring the top of heap before and after executing
mercury_main and writing out this difference. This support is only enabled
if the MR_PROFILE_SBRK macro is defined when compiling an application.
Index: runtime/mercury_memory_zones.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
retrieving revision 1.43
diff -u -p -b -r1.43 mercury_memory_zones.c
--- runtime/mercury_memory_zones.c 23 Nov 2011 10:39:38 -0000 1.43
+++ runtime/mercury_memory_zones.c 23 Nov 2011 10:46:37 -0000
@@ -76,6 +76,33 @@
#include "mercury_windows.h"
#endif
+/*
+** This macro can be used to update a high water mark of a statistic.
+*/
+#define MR_UPDATE_HIGHWATER(max, cur) \
+ do { \
+ if ((max) < (cur)) { \
+ (max) = (cur); \
+ } \
+ } while (0);
+
+#ifdef MR_PROFILE_ZONES
+/*
+** These values track the number of zones and the total size.
+*/
+#ifdef MR_THREAD_SAFE
+static MercuryLock memory_zones_stats_lock;
+#endif
+
+static MR_Integer MR_num_zones = 0;
+static MR_Integer MR_total_zone_size_net = 0;
+static MR_Integer MR_total_zone_size_gross = 0;
+
+static MR_Integer MR_max_num_zones = 0;
+static MR_Integer MR_max_total_zone_size_net = 0;
+static MR_Integer MR_max_total_zone_size_gross = 0;
+#endif
+
static void MR_setup_redzones(MR_MemoryZone *zone);
static void *MR_alloc_zone_memory(size_t size);
@@ -433,6 +460,9 @@ MR_init_zones()
{
#ifdef MR_THREAD_SAFE
pthread_mutex_init(&memory_zones_lock, MR_MUTEX_ATTR);
+#ifdef MR_PROFILE_ZONES
+ pthread_mutex_init(&memory_zones_stats_lock, MR_MUTEX_ATTR);
+#endif
#if ! defined(MR_LL_PARALLEL_CONJ)
pthread_mutex_init(&zone_id_counter_lock, MR_MUTEX_ATTR);
#endif
@@ -493,6 +523,15 @@ MR_free_zone(MR_MemoryZone *zone)
}
#endif
+#ifdef MR_PROFILE_ZONES
+ MR_LOCK(&memory_zones_stats_lock, "MR_free_zone");
+ MR_num_zones--;
+ MR_total_zone_size_net -= zone->MR_zone_desired_size;
+ MR_total_zone_size_gross -=
+ (MR_Integer)zone->MR_zone_top - (MR_Integer)zone->MR_zone_bottom;
+ MR_UNLOCK(&memory_zones_stats_lock, "MR_free_zone");
+#endif
+
MR_dealloc_zone_memory(zone->MR_zone_bottom,
((char *) zone->MR_zone_top) - ((char *) zone->MR_zone_bottom));
}
@@ -531,6 +570,10 @@ MR_remove_zone_from_used_list(MR_MemoryZ
static size_t
get_zone_alloc_size(MR_MemoryZone *zone)
{
+ /*
+ ** XXX: Check this, it seems at odds with the description with the
+ ** MR_zone_top and MR_zone_bottom fields.
+ */
#ifdef MR_PROTECTPAGE
return (size_t)((char *)zone->MR_zone_hardmax - (char *)zone->MR_zone_min);
#else
@@ -660,6 +703,17 @@ MR_create_new_zone(size_t desired_size,
*/
total_size = MR_round_up(total_size, MR_page_size);
+#ifdef MR_PROFILE_ZONES
+ MR_LOCK(&memory_zones_stats_lock, "MR_create_new_zone");
+ MR_num_zones++;
+ MR_total_zone_size_net += desired_size;
+ MR_total_zone_size_gross += total_size;
+ MR_UPDATE_HIGHWATER(MR_max_num_zones, MR_num_zones);
+ MR_UPDATE_HIGHWATER(MR_max_total_zone_size_net, MR_total_zone_size_net);
+ MR_UPDATE_HIGHWATER(MR_max_total_zone_size_gross, MR_total_zone_size_gross);
+ MR_UNLOCK(&memory_zones_stats_lock, "MR_create_new_zone");
+#endif
+
base = (MR_Word *) MR_alloc_zone_memory(total_size);
if (base == NULL) {
MR_fatal_error("Unable to allocate memory for zone");
@@ -710,6 +764,9 @@ MR_extend_zone(MR_MemoryZone *zone, size
size_t new_total_size;
MR_Integer base_incr;
int res;
+#ifdef MR_PROFILE_ZONES
+ size_t size_delta;
+#endif
if (zone == NULL) {
MR_fatal_error("MR_extend_zone called with NULL pointer");
@@ -730,6 +787,14 @@ MR_extend_zone(MR_MemoryZone *zone, size
copy_size = zone->MR_zone_end - zone->MR_zone_bottom;
offset = zone->MR_zone_min - zone->MR_zone_bottom;
+#ifdef MR_PROFILE_ZONES
+ MR_LOCK(&memory_zones_stats_lock, "MR_extend_zone");
+ MR_total_zone_size_net += new_size - zone->MR_zone_desired_size;
+ MR_total_zone_size_gross += new_total_size -
+ ((MR_Integer)zone->MR_zone_top - (MR_Integer)zone->MR_zone_bottom);
+ MR_UNLOCK(&memory_zones_stats_lock, "MR_extend_zone");
+#endif
+
#ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
/* unprotect the entire zone area */
res = MR_protect_pages((char *) zone->MR_zone_bottom,
@@ -1393,3 +1458,18 @@ MR_debug_memory_zone(FILE *fp, MR_Memory
get_zone_alloc_size(zone));
fprintf(fp, "\n");
}
+
+#ifdef MR_PROFILE_ZONES
+void MR_print_zone_stats(void) {
+ MR_LOCK(&memory_zones_stats_lock, "MR_print_zone_stats");
+ printf("Number of zones allocated: %d\n", MR_num_zones);
+ printf("Maximum number of zones allocated: %d\n", MR_max_num_zones);
+ printf("Allocated space within zones (KB) Net: %d Gross: %d\n",
+ MR_total_zone_size_net / 1024, MR_total_zone_size_gross / 1024);
+ printf("Maximum allocated space within zones (KB) Net: %d Gross: %d\n",
+ MR_max_total_zone_size_net / 1024,
+ MR_max_total_zone_size_gross / 1024);
+ MR_UNLOCK(&memory_zones_stats_lock, "MR_print_zone_stats");
+}
+#endif
+
Index: runtime/mercury_memory_zones.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.h,v
retrieving revision 1.21
diff -u -p -b -r1.21 mercury_memory_zones.h
--- runtime/mercury_memory_zones.h 5 Apr 2011 10:27:26 -0000 1.21
+++ runtime/mercury_memory_zones.h 23 Nov 2011 10:46:37 -0000
@@ -296,4 +296,11 @@ extern void MR_debug_memory_zone(FILE *
extern size_t MR_next_offset(void);
+/*
+** MR_print_zone_stats() print statistics about memory zone allocation.
+*/
+#ifdef MR_PROFILE_ZONES
+extern void MR_print_zone_stats(void);
+#endif
+
#endif /* not MERCURY_MEMORY_ZONES_H */
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.226
diff -u -p -b -r1.226 mercury_wrapper.c
--- runtime/mercury_wrapper.c 13 Oct 2011 02:42:21 -0000 1.226
+++ runtime/mercury_wrapper.c 23 Nov 2011 10:46:37 -0000
@@ -2629,6 +2629,10 @@ mercury_runtime_main(void)
MR_print_stack_frame_stats();
#endif /* MR_STACK_FRAME_STATS */
+#ifdef MR_PROFILE_ZONES
+ MR_print_zone_stats();
+#endif
+
/*
** Save the Mercury registers and restore the C callee-save registers
** before returning, since they may be used by the C code that called us.
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.124
diff -u -p -b -r1.124 mkinit.c
--- util/mkinit.c 8 Jun 2011 04:19:58 -0000 1.124
+++ util/mkinit.c 23 Nov 2011 10:47:39 -0000
@@ -320,8 +320,11 @@ static const char header1[] =
static const char header2[] =
"*/\n"
- "\n"
+ "#define _BSD_SOURCE\n"
"#include <stddef.h>\n"
+ "#ifdef MR_PROFILE_SBRK\n"
+ "#include <unistd.h>\n"
+ "#endif\n"
"#include \"mercury_init.h\"\n"
"#include \"mercury_grade.h\"\n"
"\n"
@@ -541,7 +544,21 @@ static const char main_func[] =
"int\n"
"main(int argc, char **argv)\n"
"{\n"
- " return mercury_main(argc, argv);\n"
+ "#ifdef MR_PROFILE_SBRK\n"
+ " void* old_break;\n"
+ " void* new_break;\n"
+ "#endif\n"
+ " int result;\n"
+ "#ifdef MR_PROFILE_SBRK\n"
+ " old_break = sbrk(0);\n"
+ "#endif\n"
+ " result = mercury_main(argc, argv);\n"
+ "#ifdef MR_PROFILE_SBRK\n"
+ " new_break = sbrk(0);\n"
+ " printf(\"sbrk delta: %d\\n\",\n"
+ " (MR_Integer)new_break - (MR_Integer)old_break);\n"
+ "#endif\n"
+ " return result;\n"
"}\n"
;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20111123/329b6bb6/attachment.sig>
More information about the reviews
mailing list