X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2FProfHeap.c;h=b9fc7b309cdf2c433d312bdc9dfecc033b7d8b9b;hp=4aecd0b5b3fcc6b9b92db05c4a3f290a686eba33;hb=5270423a6afe69f1dc57e5e5a474812182718d40;hpb=1cb0eb071f1316d6650f354166506789a2638720 diff --git a/rts/ProfHeap.c b/rts/ProfHeap.c index 4aecd0b..b9fc7b3 100644 --- a/rts/ProfHeap.c +++ b/rts/ProfHeap.c @@ -1,23 +1,15 @@ -/* ----------------------------------------------------------------------------- +/* ---------------------------------------------------------------------------- * * (c) The GHC Team, 1998-2003 * * Support for heap profiling * - * ---------------------------------------------------------------------------*/ - -#if defined(DEBUG) && !defined(PROFILING) -#define DEBUG_HEAP_PROF -#else -#undef DEBUG_HEAP_PROF -#endif - -#if defined(PROFILING) || defined(DEBUG_HEAP_PROF) + * --------------------------------------------------------------------------*/ #include "PosixSource.h" #include "Rts.h" + #include "RtsUtils.h" -#include "RtsFlags.h" #include "Profiling.h" #include "ProfHeap.h" #include "Stats.h" @@ -28,8 +20,6 @@ #include "Printer.h" #include -#include -#include /* ----------------------------------------------------------------------------- * era stores the current time period. It is the same as the @@ -103,77 +93,14 @@ static void aggregateCensusInfo( void ); static void dumpCensus( Census *census ); -/* ----------------------------------------------------------------------------- - Closure Type Profiling; - - PROBABLY TOTALLY OUT OF DATE -- ToDo (SDM) - -------------------------------------------------------------------------- */ - -#ifdef DEBUG_HEAP_PROF -static char *type_names[] = { - "INVALID_OBJECT" - , "CONSTR" - , "CONSTR_STATIC" - , "CONSTR_NOCAF_STATIC" - - , "FUN" - , "FUN_STATIC" - - , "THUNK" - , "THUNK_STATIC" - , "THUNK_SELECTOR" - - , "BCO" - , "AP_STACK" - , "AP" - - , "PAP" - - , "IND" - , "IND_OLDGEN" - , "IND_PERM" - , "IND_OLDGEN_PERM" - , "IND_STATIC" - - , "RET_BCO" - , "RET_SMALL" - , "RET_VEC_SMALL" - , "RET_BIG" - , "RET_VEC_BIG" - , "RET_DYN" - , "UPDATE_FRAME" - , "CATCH_FRAME" - , "STOP_FRAME" - - , "BLACKHOLE" - , "MVAR" - - , "ARR_WORDS" - - , "MUT_ARR_PTRS_CLEAN" - , "MUT_ARR_PTRS_DIRTY" - , "MUT_ARR_PTRS_FROZEN" - , "MUT_VAR_CLEAN" - , "MUT_VAR_DIRTY" - - , "WEAK" - - , "TSO" - - , "BLOCKED_FETCH" - , "FETCH_ME" +static rtsBool closureSatisfiesConstraints( StgClosure* p ); - , "EVACUATED" -}; - -#endif /* DEBUG_HEAP_PROF */ - -/* ----------------------------------------------------------------------------- +/* ---------------------------------------------------------------------------- * Find the "closure identity", which is a unique pointer reresenting * the band to which this closure's heap space is attributed in the * heap profile. * ------------------------------------------------------------------------- */ -STATIC_INLINE void * +static void * closureIdentity( StgClosure *p ) { switch (RtsFlags.ProfFlags.doHeapProfile) { @@ -184,9 +111,9 @@ closureIdentity( StgClosure *p ) case HEAP_BY_MOD: return p->header.prof.ccs->cc->module; case HEAP_BY_DESCR: - return get_itbl(p)->prof.closure_desc; + return GET_PROF_DESC(get_itbl(p)); case HEAP_BY_TYPE: - return get_itbl(p)->prof.closure_type; + return GET_PROF_TYPE(get_itbl(p)); case HEAP_BY_RETAINER: // AFAIK, the only closures in the heap which might not have a // valid retainer set are DEAD_WEAK closures. @@ -195,11 +122,25 @@ closureIdentity( StgClosure *p ) else return NULL; -#else // DEBUG - case HEAP_BY_INFOPTR: - return (void *)((StgClosure *)p)->header.info; +#else case HEAP_BY_CLOSURE_TYPE: - return type_names[get_itbl(p)->type]; + { + StgInfoTable *info; + info = get_itbl(p); + switch (info->type) { + case CONSTR: + case CONSTR_1_0: + case CONSTR_0_1: + case CONSTR_2_0: + case CONSTR_1_1: + case CONSTR_0_2: + case CONSTR_STATIC: + case CONSTR_NOCAF_STATIC: + return GET_CON_DESC(itbl_to_con_itbl(info)); + default: + return closure_type_names[info->type]; + } + } #endif default: @@ -302,6 +243,7 @@ LDV_recordDead( StgClosure *c, nat size ) /* -------------------------------------------------------------------------- * Initialize censuses[era]; * ----------------------------------------------------------------------- */ + STATIC_INLINE void initEra(Census *census) { @@ -316,10 +258,22 @@ initEra(Census *census) census->drag_total = 0; } +STATIC_INLINE void +freeEra(Census *census) +{ + if (RtsFlags.ProfFlags.bioSelector != NULL) + // when bioSelector==NULL, these are freed in heapCensus() + { + arenaFree(census->arena); + freeHashTable(census->hash, NULL); + } +} + /* -------------------------------------------------------------------------- * Increases era by 1 and initialize census[era]. * Reallocates gi[] and increases its size if needed. * ----------------------------------------------------------------------- */ + static void nextEra( void ) { @@ -343,24 +297,43 @@ nextEra( void ) initEra( &censuses[era] ); } -/* ----------------------------------------------------------------------------- - * DEBUG heap profiling, by info table - * -------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- + * Heap profiling by info table + * ------------------------------------------------------------------------- */ -#ifdef DEBUG_HEAP_PROF +#if !defined(PROFILING) FILE *hp_file; static char *hp_filename; -void initProfiling1( void ) +void initProfiling1 (void) { } -void initProfiling2( void ) +void freeProfiling1 (void) { +} + +void initProfiling2 (void) +{ + char *prog; + + prog = stgMallocBytes(strlen(prog_name) + 1, "initProfiling2"); + strcpy(prog, prog_name); +#ifdef mingw32_HOST_OS + // on Windows, drop the .exe suffix if there is one + { + char *suff; + suff = strrchr(prog,'.'); + if (suff != NULL && !strcmp(suff,".exe")) { + *suff = '\0'; + } + } +#endif + if (RtsFlags.ProfFlags.doHeapProfile) { /* Initialise the log file name */ - hp_filename = stgMallocBytes(strlen(prog_name) + 6, "hpFileName"); - sprintf(hp_filename, "%s.hp", prog_name); + hp_filename = stgMallocBytes(strlen(prog) + 6, "hpFileName"); + sprintf(hp_filename, "%s.hp", prog); /* open the log file */ if ((hp_file = fopen(hp_filename, "w")) == NULL) { @@ -371,6 +344,8 @@ void initProfiling2( void ) } } + stgFree(prog); + initHeapProfiling(); } @@ -378,7 +353,7 @@ void endProfiling( void ) { endHeapProfiling(); } -#endif /* DEBUG_HEAP_PROF */ +#endif /* !PROFILING */ static void printSample(rtsBool beginSample, StgDouble sampleValue) @@ -418,12 +393,8 @@ initHeapProfiling(void) era = 0; } - { // max_era = 2^LDV_SHIFT - nat p; - max_era = 1; - for (p = 0; p < LDV_SHIFT; p++) - max_era *= 2; - } + // max_era = 2^LDV_SHIFT + max_era = 1 << LDV_SHIFT; n_censuses = 32; censuses = stgMallocBytes(sizeof(Census) * n_censuses, "initHeapProfiling"); @@ -454,10 +425,6 @@ initHeapProfiling(void) printSample(rtsTrue, 0); printSample(rtsFalse, 0); -#ifdef DEBUG_HEAP_PROF - DEBUG_LoadSymbols(prog_name); -#endif - #ifdef PROFILING if (doingRetainerProfiling()) { initRetainerProfiling(); @@ -493,6 +460,21 @@ endHeapProfiling(void) } #endif +#ifdef PROFILING + if (doingLDVProfiling()) { + nat t; + for (t = 1; t <= era; t++) { + freeEra( &censuses[t] ); + } + } else { + freeEra( &censuses[0] ); + } +#else + freeEra( &censuses[0] ); +#endif + + stgFree(censuses); + seconds = mut_user_time(); printSample(rtsTrue, seconds); printSample(rtsFalse, seconds); @@ -553,7 +535,6 @@ fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length) } fprintf(fp, "%s", buf); } -#endif /* PROFILING */ rtsBool strMatchesSelector( char* str, char* sel ) @@ -579,14 +560,16 @@ strMatchesSelector( char* str, char* sel ) } } +#endif /* PROFILING */ + /* ----------------------------------------------------------------------------- * Figure out whether a closure should be counted in this census, by * testing against all the specified constraints. * -------------------------------------------------------------------------- */ -rtsBool +static rtsBool closureSatisfiesConstraints( StgClosure* p ) { -#ifdef DEBUG_HEAP_PROF +#if !defined(PROFILING) (void)p; /* keep gcc -Wall happy */ return rtsTrue; #else @@ -600,12 +583,12 @@ closureSatisfiesConstraints( StgClosure* p ) } if (RtsFlags.ProfFlags.descrSelector) { - b = strMatchesSelector( (get_itbl((StgClosure *)p))->prof.closure_desc, + b = strMatchesSelector( (GET_PROF_DESC(get_itbl((StgClosure *)p))), RtsFlags.ProfFlags.descrSelector ); if (!b) return rtsFalse; } if (RtsFlags.ProfFlags.typeSelector) { - b = strMatchesSelector( (get_itbl((StgClosure *)p))->prof.closure_type, + b = strMatchesSelector( (GET_PROF_TYPE(get_itbl((StgClosure *)p))), RtsFlags.ProfFlags.typeSelector ); if (!b) return rtsFalse; } @@ -791,11 +774,8 @@ dumpCensus( Census *census ) if (count == 0) continue; -#ifdef DEBUG_HEAP_PROF +#if !defined(PROFILING) switch (RtsFlags.ProfFlags.doHeapProfile) { - case HEAP_BY_INFOPTR: - fprintf(hp_file, "%s", lookupGHCName(ctr->identity)); - break; case HEAP_BY_CLOSURE_TYPE: fprintf(hp_file, "%s", (char *)ctr->identity); break; @@ -899,8 +879,6 @@ heapCensusChain( Census *census, bdescr *bd ) case IND_OLDGEN: case IND_OLDGEN_PERM: case CAF_BLACKHOLE: - case SE_CAF_BLACKHOLE: - case SE_BLACKHOLE: case BLACKHOLE: case FUN_1_0: case FUN_0_1: @@ -931,7 +909,8 @@ heapCensusChain( Census *census, bdescr *bd ) size = bco_sizeW((StgBCO *)p); break; - case MVAR: + case MVAR_CLEAN: + case MVAR_DIRTY: case WEAK: case STABLE_NAME: case MUT_VAR_CLEAN: @@ -954,7 +933,7 @@ heapCensusChain( Census *census, bdescr *bd ) case ARR_WORDS: prim = rtsTrue; - size = arr_words_sizeW(stgCast(StgArrWords*,p)); + size = arr_words_sizeW((StgArrWords*)p); break; case MUT_ARR_PTRS_CLEAN: @@ -967,10 +946,7 @@ heapCensusChain( Census *census, bdescr *bd ) case TSO: prim = rtsTrue; -#ifdef DEBUG_HEAP_PROF - size = tso_sizeW((StgTSO *)p); - break; -#else +#ifdef PROFILING if (RtsFlags.ProfFlags.includeTSOs) { size = tso_sizeW((StgTSO *)p); break; @@ -979,6 +955,9 @@ heapCensusChain( Census *census, bdescr *bd ) p += tso_sizeW((StgTSO *)p); continue; } +#else + size = tso_sizeW((StgTSO *)p); + break; #endif case TREC_HEADER: @@ -1017,11 +996,11 @@ heapCensusChain( Census *census, bdescr *bd ) identity = NULL; -#ifdef DEBUG_HEAP_PROF - real_size = size; -#else +#ifdef PROFILING // subtract the profiling overhead real_size = size - sizeofW(StgProfHeader); +#else + real_size = size; #endif if (closureSatisfiesConstraints((StgClosure*)p)) { @@ -1106,15 +1085,8 @@ heapCensus( void ) #endif // Traverse the heap, collecting the census info - - // First the small_alloc_list: we have to fix the free pointer at - // the end by calling tidyAllocatedLists() first. - tidyAllocateLists(); - heapCensusChain( census, small_alloc_list ); - - // Now traverse the heap in each generation/step. if (RtsFlags.GcFlags.generations == 1) { - heapCensusChain( census, g0s0->blocks ); + heapCensusChain( census, g0->steps[0].blocks ); } else { for (g = 0; g < RtsFlags.GcFlags.generations; g++) { for (s = 0; s < generations[g].n_steps; s++) { @@ -1141,13 +1113,13 @@ heapCensus( void ) // future restriction by biography. #ifdef PROFILING if (RtsFlags.ProfFlags.bioSelector == NULL) -#endif { freeHashTable( census->hash, NULL/* don't free the elements */ ); arenaFree( census->arena ); census->hash = NULL; census->arena = NULL; } +#endif // we're into the next time period now nextEra(); @@ -1157,5 +1129,3 @@ heapCensus( void ) #endif } -#endif /* PROFILING || DEBUG_HEAP_PROF */ -