mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 00:15:27 +00:00
Estimated hours taken: 6
Branches: main
Add a capability for measuring statistics about the stack frame usage
of a program.
configure.in:
Find out the symbolic names of the max values for the 16 and 32 bit
integer types.
runtime/mercury_conf.h.in:
Include MR_{UINT,INT}_LEAST{16,32}_MAX among the macros whose values
are determined by autoconfiguration.
runtime/mercury_conf_param.h:
Document MR_STACK_FRAME_STATS as a macro whose definition causes the
program to collect statistics on stack frame sizes.
Fix an obsolete reference: PARALLEL was renamed MR_THREAD_SAFE a long
time ago.
Document the incompatibility between MR_THREAD_SAFE and the statistics
collection flags.
runtime/mercury_stacks.h:
If MR_STACK_FRAME_STATS is defined, then record statistics every time
we create a stack frame.
runtime/mercury_stacks.c:
Define the global variables and functions needed for stack frame
statistics.
runtime/mercury_heap_profile.h:
runtime/mercury_dword.h:
Move the macros for managing 64-bit counters from
mercury_heap_profile.h to a new header file, mercury_dword.h,
since mercury_stacks.h now needs such counters too.
Rewrite the macros to make fewer assumptions, using MR_int_least64_t
and MR_int_least32_t instead of "long long" and "int".
Add expression-like forms of some of the macros for use in
mercury_stacks.h.
Rename the type MR_dword as MR_Dword.
runtime/mercury_heap_profile.c:
#include the new header file.
runtime/mercury_prof.c:
Conform to the change from MR_dword to MR_Dword.
runtime/Mmakefile:
Add the new header file to the list of header files.
runtime/mercury_wrapper.c:
If MR_STACK_FRAME_STATS is defined, initialize the stack frame stats
before execution starts and write out the statistics when execution
ends.
tools/speedtest:
Add an option that when set, causes the script to report stack frame
stats for each variant being tested.
137 lines
3.6 KiB
C
137 lines
3.6 KiB
C
/*
|
|
** Copyright (C) 1997, 1999-2001 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** File: mercury_heap_profile.c.
|
|
** Main authors: zs, fjh
|
|
**
|
|
** This module records information about the allocations of cells on the heap.
|
|
**
|
|
** The information recorded by this module is used by code in
|
|
** library/benchmarking.m.
|
|
*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#include "mercury_imp.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "mercury_prof_mem.h"
|
|
#include "mercury_dword.h"
|
|
#include "mercury_heap_profile.h"
|
|
|
|
/* all fields of these variables are initialized to 0 */
|
|
MR_memprof_counter MR_memprof_overall;
|
|
MR_memprof_table MR_memprof_procs;
|
|
MR_memprof_table MR_memprof_types;
|
|
|
|
/*
|
|
** Initialize a heap profiling counter.
|
|
*/
|
|
static void
|
|
MR_init_counter(MR_memprof_counter *counter)
|
|
{
|
|
MR_zero_dword(counter->cells_at_period_start);
|
|
MR_zero_dword(counter->words_at_period_start);
|
|
MR_zero_dword(counter->cells_since_period_start);
|
|
MR_zero_dword(counter->words_since_period_start);
|
|
}
|
|
|
|
/*
|
|
** Increment the fields in a heap profiling counter to record the allocation
|
|
** of a single cell of `size' words.
|
|
*/
|
|
static void
|
|
MR_increment_counter(MR_memprof_counter *counter, int size)
|
|
{
|
|
MR_increment_dword(counter->cells_since_period_start, 1);
|
|
MR_increment_dword(counter->words_since_period_start, size);
|
|
}
|
|
|
|
/*
|
|
** Search the specified `table' to find the entry for the given `name'
|
|
** allocating one if there isn't one already, and then increment
|
|
** the counters for that entry for an allocation of the specified `size'.
|
|
*/
|
|
static void
|
|
MR_increment_table_entry(MR_memprof_table *table, const char *name,
|
|
MR_Code *addr, int size)
|
|
{
|
|
bool found;
|
|
int diff;
|
|
MR_memprof_record **node_addr;
|
|
MR_memprof_record *node;
|
|
|
|
/*
|
|
** Search the tree to find the node with this name.
|
|
*/
|
|
found = FALSE;
|
|
node_addr = &table->root;
|
|
while ((node = *node_addr) != NULL) {
|
|
diff = strcmp(name, node->name);
|
|
if (diff < 0) {
|
|
node_addr = &node->left;
|
|
} else if (diff > 0) {
|
|
node_addr = &node->right;
|
|
} else {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If the tree didn't already contain a node with this name,
|
|
** create a new node for it.
|
|
*/
|
|
if (!found) {
|
|
char *copy_of_name;
|
|
|
|
node = MR_PROF_NEW(MR_memprof_record);
|
|
/*
|
|
** We need to make a fresh copy of the name,
|
|
** rather than just copying the pointer, because
|
|
** our caller may deallocate its copy of the name.
|
|
** Normally the name will be a string literal,
|
|
** but even then it might be a string literal from
|
|
** a dlopen()'ed module which will later get dlclose()'d.
|
|
*/
|
|
copy_of_name = MR_PROF_NEW_ARRAY(char, strlen(name) + 1);
|
|
strcpy(copy_of_name, name);
|
|
node->name = copy_of_name;
|
|
node->addr = addr;
|
|
node->left = NULL;
|
|
node->right = NULL;
|
|
MR_init_counter(&node->counter);
|
|
|
|
*node_addr = node;
|
|
|
|
table->num_entries++;
|
|
}
|
|
|
|
/* Now record the counts in this node */
|
|
MR_increment_counter(&node->counter, size);
|
|
}
|
|
|
|
/*
|
|
** Record heap profiling information for an allocation of size `size'
|
|
** in procedure `proc' for an object of type `type'.
|
|
*/
|
|
void
|
|
MR_record_allocation(int size, MR_Code *proc_addr,
|
|
const char *proc_name, const char *type)
|
|
{
|
|
/*
|
|
** Increment the overall totals,
|
|
** record the allocation in the per-procedure table, and
|
|
** record the allocation in the per-type table.
|
|
*/
|
|
MR_increment_counter(&MR_memprof_overall, size);
|
|
MR_increment_table_entry(&MR_memprof_procs, proc_name, proc_addr, size);
|
|
MR_increment_table_entry(&MR_memprof_types, type, NULL, size);
|
|
}
|