X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FProfHeap.c;h=01737549e22fe8dc09b45b1bfe854d5a1328940d;hb=80498a8a061475f74b2c093dfe97d454387581b8;hp=be386b82f08895f076c64d71ed4646dba6b9eabb;hpb=f18299252ddad0c224985a6545761fec6a9c5def;p=ghc-hetmet.git diff --git a/ghc/rts/ProfHeap.c b/ghc/rts/ProfHeap.c index be386b8..0173754 100644 --- a/ghc/rts/ProfHeap.c +++ b/ghc/rts/ProfHeap.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: ProfHeap.c,v 1.30 2001/11/28 15:43:23 simonmar Exp $ + * $Id: ProfHeap.c,v 1.38 2002/08/16 13:29:06 simonmar Exp $ * * (c) The GHC Team, 1998-2000 * @@ -30,6 +30,8 @@ #include "Arena.h" #include "Printer.h" +#include + /* ----------------------------------------------------------------------------- * era stores the current time period. It is the same as the * number of censuses that have been performed. @@ -37,7 +39,7 @@ * RESTRICTION: * era must be no longer than LDV_SHIFT (15 or 30) bits. * Invariants: - * era is initialized to 0 in initHeapProfiling(). + * era is initialized to 1 in initHeapProfiling(). * * max_era is initialized to 2^LDV_SHIFT in initHeapProfiling(). * When era reaches max_era, the profiling stops because a closure can @@ -93,8 +95,8 @@ typedef struct { int drag_total; } Census; -Census *censuses = NULL; -nat n_censuses = 0; +static Census *censuses = NULL; +static nat n_censuses = 0; #ifdef PROFILING static void aggregateCensusInfo( void ); @@ -181,20 +183,27 @@ closureIdentity( StgClosure *p ) #ifdef PROFILING case HEAP_BY_CCS: - return ((StgClosure *)p)->header.prof.ccs; + return p->header.prof.ccs; case HEAP_BY_MOD: - return ((StgClosure *)p)->header.prof.ccs->cc->module; + return p->header.prof.ccs->cc->module; case HEAP_BY_DESCR: - return (get_itbl((StgClosure *)p))->prof.closure_desc; + return get_itbl(p)->prof.closure_desc; case HEAP_BY_TYPE: - return (get_itbl((StgClosure *)p))->prof.closure_type; + return get_itbl(p)->prof.closure_type; case HEAP_BY_RETAINER: - return retainerSetOf((StgClosure *)p); + // AFAIK, the only closures in the heap which might not have a + // valid retainer set are DEAD_WEAK closures. + if (isRetainerSetFieldValid(p)) + return retainerSetOf(p); + else + return NULL; + #else // DEBUG case HEAP_BY_INFOPTR: return (void *)((StgClosure *)p)->header.info; case HEAP_BY_CLOSURE_TYPE: return type_names[get_itbl(p)->type]; + #endif default: barf("closureIdentity"); @@ -366,6 +375,13 @@ initHeapProfiling(void) return 0; } +#ifdef PROFILING + if (doingLDVProfiling() && doingRetainerProfiling()) { + prog_belch("cannot mix -hb and -hr"); + stg_exit(1); + } +#endif + // we only count eras if we're doing LDV profiling. Otherwise era // is fixed at zero. #ifdef PROFILING @@ -442,17 +458,9 @@ endHeapProfiling(void) #endif #ifdef PROFILING - // Note: - // We do not need to perform a major garbage collection because all the - // closures created since the last census will not affect the profiling - // statistics anyhow. - if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_LDV) - LdvCensusKillAll(); -#endif - -#ifdef PROFILING - if (RtsFlags.ProfFlags.bioSelector != NULL) { + if (doingLDVProfiling()) { nat t; + LdvCensusKillAll(); aggregateCensusInfo(); for (t = 1; t < era; t++) { dumpCensus( &censuses[t] ); @@ -483,6 +491,8 @@ fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length) return; } + fprintf(fp, "(%d)", ccs->ccsID); + // keep printing components of the stack until we run out of space // in the buffer. If we run out of space, end with "...". for (; ccs != NULL && ccs != CCS_MAIN; ccs = ccs->prevStack) { @@ -490,18 +500,28 @@ fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length) // CAF cost centres print as M.CAF, but we leave the module // name out of all the others to save space. if (!strcmp(ccs->cc->label,"CAF")) { +#ifdef HAVE_SNPRINTF written = snprintf(buf+next_offset, (int)max_length-3-(int)next_offset, "%s.CAF", ccs->cc->module); +#else + written = sprintf(buf+next_offset, + "%s.CAF", ccs->cc->module); +#endif } else { if (ccs->prevStack != NULL && ccs->prevStack != CCS_MAIN) { template = "%s/"; } else { template = "%s"; } +#ifdef HAVE_SNPRINTF written = snprintf(buf+next_offset, (int)max_length-3-(int)next_offset, template, ccs->cc->label); +#else + written = sprintf(buf+next_offset, + template, ccs->cc->label); +#endif } if (next_offset+written >= max_length-4) { @@ -513,9 +533,10 @@ fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length) } fprintf(fp, "%s", buf); } +#endif // PROFILING -static rtsBool -str_matches_selector( char* str, char* sel ) +rtsBool +strMatchesSelector( char* str, char* sel ) { char* p; // fprintf(stderr, "str_matches_selector %s %s\n", str, sel); @@ -537,7 +558,6 @@ str_matches_selector( char* str, char* sel ) if (*sel == '\0') return rtsFalse; } } -#endif // PROFILING /* ----------------------------------------------------------------------------- * Figure out whether a closure should be counted in this census, by @@ -550,33 +570,31 @@ closureSatisfiesConstraints( StgClosure* p ) return rtsTrue; #else rtsBool b; - if (RtsFlags.ProfFlags.modSelector) { - b = str_matches_selector( ((StgClosure *)p)->header.prof.ccs->cc->module, - RtsFlags.ProfFlags.modSelector ); - if (!b) return rtsFalse; + + // The CCS has a selected field to indicate whether this closure is + // deselected by not being mentioned in the module, CC, or CCS + // selectors. + if (!p->header.prof.ccs->selected) { + return rtsFalse; } + if (RtsFlags.ProfFlags.descrSelector) { - b = str_matches_selector( (get_itbl((StgClosure *)p))->prof.closure_desc, + b = strMatchesSelector( (get_itbl((StgClosure *)p))->prof.closure_desc, RtsFlags.ProfFlags.descrSelector ); if (!b) return rtsFalse; } if (RtsFlags.ProfFlags.typeSelector) { - b = str_matches_selector( (get_itbl((StgClosure *)p))->prof.closure_type, + b = strMatchesSelector( (get_itbl((StgClosure *)p))->prof.closure_type, RtsFlags.ProfFlags.typeSelector ); if (!b) return rtsFalse; } - if (RtsFlags.ProfFlags.ccSelector) { - b = str_matches_selector( ((StgClosure *)p)->header.prof.ccs->cc->label, - RtsFlags.ProfFlags.ccSelector ); - if (!b) return rtsFalse; - } if (RtsFlags.ProfFlags.retainerSelector) { RetainerSet *rs; nat i; rs = retainerSetOf((StgClosure *)p); if (rs != NULL) { for (i = 0; i < rs->num; i++) { - b = str_matches_selector( rs->element[i]->cc->label, + b = strMatchesSelector( rs->element[i]->cc->label, RtsFlags.ProfFlags.retainerSelector ); if (b) return rtsTrue; } @@ -613,23 +631,8 @@ aggregateCensusInfo( void ) drag_total += censuses[t].drag_total; censuses[t].void_total = void_total; censuses[t].drag_total = drag_total; - ASSERT( censuses[t].void_total < censuses[t].not_used ); - ASSERT( censuses[t].drag_total < censuses[t].used ); - } - - for (t = 1; t < era; t++) { // note: start at 1, not 0 - fprintf(hp_file, "MARK %f\n", censuses[t].time); - fprintf(hp_file, "BEGIN_SAMPLE %f\n", censuses[t].time); - fprintf(hp_file, "VOID\t%u\n", censuses[t].void_total * sizeof(W_)); - fprintf(hp_file, "LAG\t%u\n", - (censuses[t].not_used - censuses[t].void_total) - * sizeof(W_)); - fprintf(hp_file, "USE\t%u\n", - (censuses[t].used - censuses[t].drag_total) * sizeof(W_)); - fprintf(hp_file, "INHERENT_USE\t%u\n", - censuses[t].prim * sizeof(W_)); - fprintf(hp_file, "DRAG\t%u\n", censuses[t].drag_total * sizeof(W_)); - fprintf(hp_file, "END_SAMPLE %f\n", censuses[t].time); + ASSERT( censuses[t].void_total <= censuses[t].not_used ); + ASSERT( censuses[t].drag_total <= censuses[t].used ); } return; @@ -706,18 +709,34 @@ dumpCensus( Census *census ) fprintf(hp_file, "BEGIN_SAMPLE %0.2f\n", census->time); +#ifdef PROFILING + if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_LDV) { + fprintf(hp_file, "VOID\t%u\n", census->void_total * sizeof(W_)); + fprintf(hp_file, "LAG\t%u\n", + (census->not_used - census->void_total) * sizeof(W_)); + fprintf(hp_file, "USE\t%u\n", + (census->used - census->drag_total) * sizeof(W_)); + fprintf(hp_file, "INHERENT_USE\t%u\n", + census->prim * sizeof(W_)); + fprintf(hp_file, "DRAG\t%u\n", census->drag_total * + sizeof(W_)); + fprintf(hp_file, "END_SAMPLE %0.2f\n", census->time); + return; + } +#endif + for (ctr = census->ctrs; ctr != NULL; ctr = ctr->next) { #ifdef PROFILING if (RtsFlags.ProfFlags.bioSelector != NULL) { count = 0; - if (str_matches_selector("lag", RtsFlags.ProfFlags.bioSelector)) + if (strMatchesSelector("lag", RtsFlags.ProfFlags.bioSelector)) count += ctr->c.ldv.not_used - ctr->c.ldv.void_total; - if (str_matches_selector("drag", RtsFlags.ProfFlags.bioSelector)) + if (strMatchesSelector("drag", RtsFlags.ProfFlags.bioSelector)) count += ctr->c.ldv.drag_total; - if (str_matches_selector("void", RtsFlags.ProfFlags.bioSelector)) + if (strMatchesSelector("void", RtsFlags.ProfFlags.bioSelector)) count += ctr->c.ldv.void_total; - if (str_matches_selector("use", RtsFlags.ProfFlags.bioSelector)) + if (strMatchesSelector("use", RtsFlags.ProfFlags.bioSelector)) count += ctr->c.ldv.used - ctr->c.ldv.drag_total; } else #endif @@ -743,7 +762,7 @@ dumpCensus( Census *census ) #ifdef PROFILING switch (RtsFlags.ProfFlags.doHeapProfile) { case HEAP_BY_CCS: - fprint_ccs(hp_file, (CostCentreStack *)ctr->identity, 30); + fprint_ccs(hp_file, (CostCentreStack *)ctr->identity, 25); break; case HEAP_BY_MOD: case HEAP_BY_DESCR: