/* -----------------------------------------------------------------------------
- * $Id: Profiling.c,v 1.13 2000/02/29 16:58:09 simonmar Exp $
+ * $Id: Profiling.c,v 1.18 2000/04/05 15:21:28 simonmar Exp $
*
- * (c) The GHC Team, 1998-1999
+ * (c) The GHC Team, 1998-2000
*
* Support for profiling
*
#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"
/* Globals for opening the profiling log file
*/
static char *prof_filename; /* prof report file name = <program>.prof */
-static FILE *prof_file;
+FILE *prof_file;
/* The Current Cost Centre Stack (for attributing costs)
*/
* 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;
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
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());
{
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);
+ fprintf(prof_file, "%d %d \"%s\" \"%s\"\n",
+ CC_UQ, cc->ccID, cc->label, cc->module);
}
}
}
}
/* -----------------------------------------------------------------------------
- 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;
}
new_ccs->mem_alloc = 0;
new_ccs->root = ccs->root;
- new_ccs->emitted = 0;
/* update the memoization table for the parent stack */
if (ccs != EMPTY_STACK)
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",