/* -----------------------------------------------------------------------------
- * $Id: Profiling.c,v 1.15 2000/03/07 11:53:12 simonmar Exp $
+ * $Id: Profiling.c,v 1.19 2000/04/19 12:42:48 simonmar Exp $
*
* (c) The GHC Team, 1998-2000
*
#include "Rts.h"
#include "RtsUtils.h"
#include "RtsFlags.h"
-#include "ProfRts.h"
-#include "StgRun.h"
-#include "StgStartup.h"
+#include "Profiling.h"
#include "Storage.h"
#include "Proftimer.h"
#include "Itimer.h"
*/
static lnat total_alloc, total_prof_ticks;
-/* Globals for opening the profiling log file
+/* Globals for opening the profiling log file(s)
*/
static char *prof_filename; /* prof report file name = <program>.prof */
FILE *prof_file;
+static char *hp_filename; /* heap profile (hp2ps style) log file */
+FILE *hp_file;
+
/* The Current Cost Centre Stack (for attributing costs)
*/
CostCentreStack *CCCS;
* SUBSUMED is the one-and-only CCS placed on top-level functions.
* It indicates that all costs are to be attributed to the
* enclosing cost centre stack. SUBSUMED never accumulates
- * any costs.
+ * any costs. The is_caf flag is set on the subsumed cost
+ * centre.
*
* DONT_CARE is a placeholder cost-centre we assign to static
* constructors. It should *never* accumulate any costs.
*/
-CC_DECLARE(CC_MAIN, "MAIN", "MAIN", "MAIN", CC_IS_BORING,);
-CC_DECLARE(CC_SYSTEM, "SYSTEM", "MAIN", "MAIN", CC_IS_BORING,);
-CC_DECLARE(CC_GC, "GC", "GC", "GC", CC_IS_BORING,);
-CC_DECLARE(CC_OVERHEAD, "OVERHEAD_of", "PROFILING", "PROFILING", CC_IS_CAF,);
-CC_DECLARE(CC_SUBSUMED, "SUBSUMED", "MAIN", "MAIN", CC_IS_SUBSUMED,);
-CC_DECLARE(CC_DONTZuCARE,"DONT_CARE", "MAIN", "MAIN", CC_IS_BORING,);
+CC_DECLARE(CC_MAIN, "MAIN", "MAIN", CC_IS_BORING, );
+CC_DECLARE(CC_SYSTEM, "SYSTEM", "MAIN", CC_IS_BORING, );
+CC_DECLARE(CC_GC, "GC", "GC", CC_IS_BORING, );
+CC_DECLARE(CC_OVERHEAD, "OVERHEAD_of", "PROFILING", CC_IS_CAF, );
+CC_DECLARE(CC_SUBSUMED, "SUBSUMED", "MAIN", CC_IS_CAF, );
+CC_DECLARE(CC_DONT_CARE, "DONT_CARE", "MAIN", CC_IS_BORING, );
-CCS_DECLARE(CCS_MAIN, CC_MAIN, CC_IS_BORING, );
-CCS_DECLARE(CCS_SYSTEM, CC_SYSTEM, CC_IS_BORING, );
-CCS_DECLARE(CCS_GC, CC_GC, CC_IS_BORING, );
-CCS_DECLARE(CCS_OVERHEAD, CC_OVERHEAD, CC_IS_CAF, );
-CCS_DECLARE(CCS_SUBSUMED, CC_SUBSUMED, CC_IS_SUBSUMED, );
-CCS_DECLARE(CCS_DONTZuCARE, CC_DONTZuCARE, CC_IS_BORING, );
+CCS_DECLARE(CCS_MAIN, CC_MAIN, );
+CCS_DECLARE(CCS_SYSTEM, CC_SYSTEM, );
+CCS_DECLARE(CCS_GC, CC_GC, );
+CCS_DECLARE(CCS_OVERHEAD, CC_OVERHEAD, );
+CCS_DECLARE(CCS_SUBSUMED, CC_SUBSUMED, );
+CCS_DECLARE(CCS_DONT_CARE, CC_DONT_CARE, );
/*
* Uniques for the XML log-file format
static CostCentreStack * ActualPush_ ( CostCentreStack *ccs, CostCentre *cc,
CostCentreStack *new_ccs );
-static void registerCostCentres ( void );
static rtsBool ccs_to_ignore ( CostCentreStack *ccs );
static void count_ticks ( CostCentreStack *ccs );
static void reportCCS ( CostCentreStack *ccs, nat indent );
-------------------------------------------------------------------------- */
void
-initProfiling (void)
+initProfiling1 (void)
{
- CostCentreStack *ccs, *next;
-
/* for the benefit of allocate()... */
CCCS = CCS_SYSTEM;
-
+
/* Initialize counters for IDs */
CC_ID = 1;
CCS_ID = 1;
REGISTER_CC(CC_GC);
REGISTER_CC(CC_OVERHEAD);
REGISTER_CC(CC_SUBSUMED);
- REGISTER_CC(CC_DONTZuCARE);
+ REGISTER_CC(CC_DONT_CARE);
REGISTER_CCS(CCS_MAIN);
REGISTER_CCS(CCS_SYSTEM);
REGISTER_CCS(CCS_GC);
REGISTER_CCS(CCS_OVERHEAD);
REGISTER_CCS(CCS_SUBSUMED);
- REGISTER_CCS(CCS_DONTZuCARE);
+ REGISTER_CCS(CCS_DONT_CARE);
CCCS = CCS_OVERHEAD;
- registerCostCentres();
+
+ /* cost centres are registered by the per-module
+ * initialisation code now...
+ */
+}
+
+void
+initProfiling2 (void)
+{
+ CostCentreStack *ccs, *next;
+
CCCS = CCS_SYSTEM;
/* Set up the log file, and dump the header and cost centre
- * information into it.
- */
+ * information into it. */
initProfilingLogFile();
/* find all the "special" cost centre stacks, and make them children
static void
initProfilingLogFile(void)
{
- /* Initialise the log file name */
- prof_filename = stgMallocBytes(strlen(prog_argv[0]) + 6, "initProfiling");
- sprintf(prof_filename, "%s.prof", prog_argv[0]);
-
- /* open the log file */
- if ((prof_file = fopen(prof_filename, "w")) == NULL) {
- fprintf(stderr, "Can't open profiling report file %s\n", prof_filename);
- RtsFlags.CcFlags.doCostCentres = 0;
- return;
- }
+ /* Initialise the log file name */
+ prof_filename = stgMallocBytes(strlen(prog_argv[0]) + 6, "initProfiling");
+ sprintf(prof_filename, "%s.prof", prog_argv[0]);
+
+ /* open the log file */
+ if ((prof_file = fopen(prof_filename, "w")) == NULL) {
+ fprintf(stderr, "Can't open profiling report file %s\n", prof_filename);
+ RtsFlags.CcFlags.doCostCentres = 0;
+ return;
+ }
- if (RtsFlags.CcFlags.doCostCentres == COST_CENTRES_XML) {
- /* dump the time, and the profiling interval */
- fprintf(prof_file, "\"%s\"\n", time_str());
- fprintf(prof_file, "\"%d ms\"\n", TICK_MILLISECS);
+ if (RtsFlags.CcFlags.doCostCentres == COST_CENTRES_XML) {
+ /* dump the time, and the profiling interval */
+ fprintf(prof_file, "\"%s\"\n", time_str());
+ fprintf(prof_file, "\"%d ms\"\n", TICK_MILLISECS);
+
+ /* declare all the cost centres */
+ {
+ CostCentre *cc;
+ for (cc = CC_LIST; cc != NULL; cc = cc->link) {
+ fprintf(prof_file, "%d %d \"%s\" \"%s\"\n",
+ CC_UQ, cc->ccID, cc->label, cc->module);
+ }
+ }
+ }
- /* declare all the cost centres */
- {
- CostCentre *cc;
- for (cc = CC_LIST; cc != NULL; cc = cc->link) {
- fprintf(prof_file, "%d %d \"%s\" \"%s\" \"%s\"\n",
- CC_UQ, cc->ccID, cc->label, cc->module, cc->group);
- }
+ if (RtsFlags.ProfFlags.doHeapProfile) {
+ /* Initialise the log file name */
+ hp_filename = stgMallocBytes(strlen(prog_argv[0]) + 6, "initProfiling");
+ sprintf(hp_filename, "%s.hp", prog_argv[0]);
+
+ /* open the log file */
+ if ((hp_file = fopen(hp_filename, "w")) == NULL) {
+ fprintf(stderr, "Can't open profiling report file %s\n",
+ hp_filename);
+ RtsFlags.ProfFlags.doHeapProfile = 0;
+ return;
+ }
}
- }
}
void
}
/* -----------------------------------------------------------------------------
- Register Cost Centres
-
- At the moment, this process just supplies a unique integer to each
- statically declared cost centre and cost centre stack in the
- program.
-
- The code generator inserts a small function "reg<moddule>" in each
- module which registers any cost centres from that module and calls
- the registration functions in each of the modules it imports. So,
- if we call "regMain", each reachable module in the program will be
- registered.
-
- The reg* functions are compiled in the same way as STG code,
- i.e. without normal C call/return conventions. Hence we must use
- StgRun to call this stuff.
- -------------------------------------------------------------------------- */
-
-/* The registration functions use an explicit stack...
- */
-#define REGISTER_STACK_SIZE (BLOCK_SIZE * 4)
-F_ *register_stack;
-
-static void
-registerCostCentres ( void )
-{
- /* this storage will be reclaimed by the garbage collector,
- * as a large block.
- */
- register_stack = (F_ *)allocate(REGISTER_STACK_SIZE / sizeof(W_));
-
- StgRun((StgFunPtr)stg_register, &MainRegTable);
-}
-
-
-/* -----------------------------------------------------------------------------
- Set cost centre stack when entering a function. Here we implement
- the rule
-
- "if CCSfn is an initial segment of CCCS,
- then set CCCS to CCSfn,
- else append CCSfn to CCCS"
+ Set cost centre stack when entering a function.
-------------------------------------------------------------------------- */
rtsBool entering_PAP;
return CCCS;
}
- if (cccs->root == ccsfn->root) {
- return ccsfn;
- } else {
+ if (ccsfn->root->is_caf == CC_IS_CAF) {
return AppendCCS(cccs,ccsfn);
+ } else {
+ return ccsfn;
}
}
return ccs1;
}
- if (ccs2->cc->is_subsumed != CC_IS_BORING) {
+ if (ccs2->cc->is_caf == CC_IS_CAF) {
return ccs1;
}
if (ccs != CCS_MAIN)
{
print_ccs(fp, ccs->prevStack);
- fprintf(fp, "->[%s,%s,%s]",
- ccs->cc->label, ccs->cc->module, ccs->cc->group);
+ fprintf(fp, "->[%s,%s]", ccs->cc->label, ccs->cc->module);
} else {
- fprintf(fp, "[%s,%s,%s]",
- ccs->cc->label, ccs->cc->module, ccs->cc->group);
+ fprintf(fp, "[%s,%s]", ccs->cc->label, ccs->cc->module);
}
if (ccs == CCCS) {
{
fprintf(prof_file, "%-24s %-10s", "COST CENTRE", "MODULE");
-#ifdef NOT_YET
- do_groups = have_interesting_groups(Registered_CC);
- if (do_groups) fprintf(prof_file, " %-11.11s", "GROUP");
-#endif
-
fprintf(prof_file, "%8s %5s %5s %8s %5s", "scc", "%time", "%alloc", "inner", "cafs");
if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) {
{
nat count;
char temp[128]; /* sigh: magic constant */
-#ifdef NOT_YET
- rtsBool do_groups = rtsFalse;
-#endif
stopProfTimer();
fprintf(prof_file, "%-*s%-*s %-10s",
indent, "", 24-indent, cc->label, cc->module);
-#ifdef NOT_YET
- if (do_groups) fprintf(prof_file, " %-11.11s",cc->group);
-#endif
-
fprintf(prof_file, "%8ld %5.1f %5.1f %8ld %5ld",
ccs->scc_count,
total_prof_ticks == 0 ? 0.0 : (ccs->time_ticks / (StgFloat) total_prof_ticks * 100),
ccs_to_ignore (CostCentreStack *ccs)
{
if ( ccs == CCS_OVERHEAD
- || ccs == CCS_DONTZuCARE
+ || ccs == CCS_DONT_CARE
|| ccs == CCS_GC
|| ccs == CCS_SYSTEM) {
return rtsTrue;
CostCentre *cc;
IndexTable *i;
+ if (ccs_to_ignore(ccs)) { return; }
+
cc = ccs->cc;
fprintf(prof_file, " 1 %d %lu %lu %lu",