X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FProfiling.c;h=b40b29830acec37b8fceb6bd7e97aebc4950f467;hb=6d35596c37601a9bf608e32034c390d516454c29;hp=fd5dc92158e18c638d19e08f72de4a3388bbdbce;hpb=88740ad379e77efc892ecbef82cde626ee9a6bd9;p=ghc-hetmet.git diff --git a/ghc/rts/Profiling.c b/ghc/rts/Profiling.c index fd5dc92..b40b298 100644 --- a/ghc/rts/Profiling.c +++ b/ghc/rts/Profiling.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Profiling.c,v 1.15 2000/03/07 11:53:12 simonmar Exp $ + * $Id: Profiling.c,v 1.20 2000/05/12 13:01:04 simonmar Exp $ * * (c) The GHC Team, 1998-2000 * @@ -12,9 +12,7 @@ #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" @@ -48,11 +46,14 @@ rtsBool time_profiling = rtsFalse; */ 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 = .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; @@ -83,25 +84,26 @@ CostCentreStack *CCS_LIST; * 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 @@ -117,22 +119,21 @@ CCS_DECLARE(CCS_DONTZuCARE, CC_DONTZuCARE, CC_IS_BORING, ); * Static Functions */ -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 ); -static void DecCCS ( CostCentreStack *ccs ); -static void DecBackEdge ( CostCentreStack *ccs, CostCentreStack *oldccs ); -static CostCentreStack *CheckLoop ( CostCentreStack *ccs, CostCentre *cc ); -static CostCentreStack *pruneCCSTree ( CostCentreStack *ccs ); - -static CostCentreStack *ActualPush ( CostCentreStack *, CostCentre * ); -static CostCentreStack *IsInIndexTable ( IndexTable *, CostCentre * ); -static IndexTable *AddToIndexTable ( IndexTable *, CostCentreStack *, - CostCentre *, unsigned int ); +static CostCentreStack * ActualPush_ ( CostCentreStack *ccs, CostCentre *cc, + CostCentreStack *new_ccs ); +static rtsBool ccs_to_ignore ( CostCentreStack *ccs ); +static void count_ticks ( CostCentreStack *ccs ); +static void inherit_costs ( CostCentreStack *ccs ); +static void reportCCS ( CostCentreStack *ccs, nat indent ); +static void DecCCS ( CostCentreStack *ccs ); +static void DecBackEdge ( CostCentreStack *ccs, + CostCentreStack *oldccs ); +static CostCentreStack * CheckLoop ( CostCentreStack *ccs, CostCentre *cc ); +static CostCentreStack * pruneCCSTree ( CostCentreStack *ccs ); +static CostCentreStack * ActualPush ( CostCentreStack *, CostCentre * ); +static CostCentreStack * IsInIndexTable ( IndexTable *, CostCentre * ); +static IndexTable * AddToIndexTable ( IndexTable *, CostCentreStack *, + CostCentre *, unsigned int ); #ifdef DEBUG static void printCCS ( CostCentreStack *ccs ); @@ -147,13 +148,11 @@ static void reportCCS_XML ( CostCentreStack *ccs ); -------------------------------------------------------------------------- */ 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; @@ -171,21 +170,30 @@ initProfiling (void) 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 @@ -214,31 +222,45 @@ initProfiling (void) 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 @@ -262,47 +284,7 @@ endProfiling ( 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" 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; @@ -315,10 +297,10 @@ EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn ) 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; } } @@ -413,7 +395,7 @@ AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 ) return ccs1; } - if (ccs2->cc->is_subsumed != CC_IS_BORING) { + if (ccs2->cc->is_caf == CC_IS_CAF) { return ccs1; } @@ -449,14 +431,14 @@ ActualPush_ ( CostCentreStack *ccs, CostCentre *cc, CostCentreStack *new_ccs ) /* Initialise the various _scc_ counters to zero */ new_ccs->scc_count = 0; - new_ccs->sub_scc_count = 0; - new_ccs->sub_cafcc_count = 0; /* Initialize all other stats here. There should be a quick way * that's easily used elsewhere too */ new_ccs->time_ticks = 0; new_ccs->mem_alloc = 0; + new_ccs->inherited_ticks = 0; + new_ccs->inherited_alloc = 0; new_ccs->root = ccs->root; @@ -505,29 +487,6 @@ AddToIndexTable(IndexTable *it, CostCentreStack *new_ccs, } -void -print_ccs (FILE *fp, CostCentreStack *ccs) -{ - if (ccs == CCCS) { - fprintf(fp, "Cost-Centre Stack: "); - } - - if (ccs != CCS_MAIN) - { - print_ccs(fp, ccs->prevStack); - fprintf(fp, "->[%s,%s,%s]", - ccs->cc->label, ccs->cc->module, ccs->cc->group); - } else { - fprintf(fp, "[%s,%s,%s]", - ccs->cc->label, ccs->cc->module, ccs->cc->group); - } - - if (ccs == CCCS) { - fprintf(fp, "\n"); - } -} - - static void DecCCS(CostCentreStack *ccs) { @@ -645,14 +604,10 @@ report_per_cc_costs( void ) static void fprint_header( void ) { - 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, "%-24s %-10s individual inherited\n", "", ""); - fprintf(prof_file, "%8s %5s %5s %8s %5s", "scc", "%time", "%alloc", "inner", "cafs"); + fprintf(prof_file, "%-24s %-10s", "COST CENTRE", "MODULE"); + fprintf(prof_file, "%8s %5s %5s %5s %5s", "entries", "%time", "%alloc", "%time", "%alloc"); if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) { fprintf(prof_file, " %5s %9s", "ticks", "bytes"); @@ -670,9 +625,6 @@ report_ccs_profiling( void ) { nat count; char temp[128]; /* sigh: magic constant */ -#ifdef NOT_YET - rtsBool do_groups = rtsFalse; -#endif stopProfTimer(); @@ -718,6 +670,8 @@ report_ccs_profiling( void ) report_per_cc_costs(); + inherit_costs(CCS_MAIN); + fprint_header(); reportCCS(pruneCCSTree(CCS_MAIN), 0); @@ -742,16 +696,14 @@ reportCCS(CostCentreStack *ccs, nat indent) 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", + fprintf(prof_file, "%8ld %5.1f %5.1f %5.1f %5.1f", ccs->scc_count, total_prof_ticks == 0 ? 0.0 : (ccs->time_ticks / (StgFloat) total_prof_ticks * 100), total_alloc == 0 ? 0.0 : (ccs->mem_alloc / (StgFloat) total_alloc * 100), - ccs->sub_scc_count, ccs->sub_cafcc_count); - + total_prof_ticks == 0 ? 0.0 : (ccs->inherited_ticks / (StgFloat) total_prof_ticks * 100), + total_alloc == 0 ? 0.0 : (ccs->inherited_alloc / (StgFloat) total_alloc * 100) + ); + if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) { fprintf(prof_file, " %5ld %9ld", ccs->time_ticks, ccs->mem_alloc*sizeof(W_)); #if defined(PROFILING_DETAIL_COUNTS) @@ -790,6 +742,28 @@ count_ticks(CostCentreStack *ccs) } } +/* Traverse the cost centre stack tree and inherit ticks & allocs. + */ +static void +inherit_costs(CostCentreStack *ccs) +{ + IndexTable *i; + + if (ccs_to_ignore(ccs)) { return; } + + ccs->inherited_ticks += ccs->time_ticks; + ccs->inherited_alloc += ccs->mem_alloc; + + for (i = ccs->indexTable; i != NULL; i = i->next) + if (!i->back_edge) { + inherit_costs(i->ccs); + ccs->inherited_ticks += i->ccs->inherited_ticks; + ccs->inherited_alloc += i->ccs->inherited_alloc; + } + + return; +} + /* return rtsTrue if it is one of the ones that * should not be reported normally (because it confuses * the users) @@ -798,7 +772,7 @@ static rtsBool ccs_to_ignore (CostCentreStack *ccs) { if ( ccs == CCS_OVERHEAD - || ccs == CCS_DONTZuCARE + || ccs == CCS_DONT_CARE || ccs == CCS_GC || ccs == CCS_SYSTEM) { return rtsTrue; @@ -829,17 +803,11 @@ pruneCCSTree( CostCentreStack *ccs ) /* force printing of *all* cost centres if -P -P */ ) || ( ccs->indexTable != 0 ) - || ( (ccs->scc_count || ccs->sub_scc_count || - ccs->time_ticks || ccs->mem_alloc - || (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE - && (ccs->sub_cafcc_count -#if defined(PROFILING_DETAIL_COUNTS) - || cc->thunk_count || cc->function_count || cc->pap_count -#endif - ))))) { - return ccs; + || ( ccs->scc_count || ccs->time_ticks || ccs->mem_alloc ) + ) { + return ccs; } else { - return NULL; + return NULL; } } @@ -865,6 +833,8 @@ reportCCS_XML(CostCentreStack *ccs) CostCentre *cc; IndexTable *i; + if (ccs_to_ignore(ccs)) { return; } + cc = ccs->cc; fprintf(prof_file, " 1 %d %lu %lu %lu", @@ -877,6 +847,27 @@ reportCCS_XML(CostCentreStack *ccs) } } +void +print_ccs (FILE *fp, CostCentreStack *ccs) +{ + if (ccs == CCCS) { + fprintf(fp, "Cost-Centre Stack: "); + } + + if (ccs != CCS_MAIN) + { + print_ccs(fp, ccs->prevStack); + fprintf(fp, "->[%s,%s]", ccs->cc->label, ccs->cc->module); + } else { + fprintf(fp, "[%s,%s]", ccs->cc->label, ccs->cc->module); + } + + if (ccs == CCCS) { + fprintf(fp, "\n"); + } +} + + #ifdef DEBUG static void printCCS ( CostCentreStack *ccs )