X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FProfHeap.c;h=312bee735c16c885f60a588bfa846efa647086a8;hb=0dbbf1932d550293986af6244202cb735b2cd966;hp=c47554521a351586e05ecbbd99f81bd4dfdd3375;hpb=b0ac0f91743a0240fcf45c6d377a920c4fcfd69d;p=ghc-hetmet.git diff --git a/ghc/rts/ProfHeap.c b/ghc/rts/ProfHeap.c index c475545..312bee7 100644 --- a/ghc/rts/ProfHeap.c +++ b/ghc/rts/ProfHeap.c @@ -23,7 +23,6 @@ #include "ProfHeap.h" #include "Stats.h" #include "Hash.h" -#include "StrHash.h" #include "RetainerProfile.h" #include "LdvProfile.h" #include "Arena.h" @@ -150,17 +149,17 @@ static char *type_names[] = { , "STOP_FRAME" , "BLACKHOLE" - , "BLACKHOLE_BQ" , "MVAR" , "ARR_WORDS" - , "MUT_ARR_PTRS" + , "MUT_ARR_PTRS_CLEAN" + , "MUT_ARR_PTRS_DIRTY" , "MUT_ARR_PTRS_FROZEN" - , "MUT_VAR" + , "MUT_VAR_CLEAN" + , "MUT_VAR_DIRTY" , "WEAK" - , "FOREIGN" , "TSO" @@ -256,6 +255,7 @@ LDV_recordDead( StgClosure *c, nat size ) if (RtsFlags.ProfFlags.bioSelector == NULL) { censuses[t].void_total += (int)size; censuses[era].void_total -= (int)size; + ASSERT(censuses[t].void_total < censuses[t].not_used); } else { id = closureIdentity(c); ctr = lookupHashTable(censuses[t].hash, (StgWord)id); @@ -390,7 +390,7 @@ printSample(rtsBool beginSample, StgDouble sampleValue) fractionalPart = modf(sampleValue, &integralPart); fprintf(hp_file, "%s %d.%02d\n", (beginSample ? "BEGIN_SAMPLE" : "END_SAMPLE"), - (int)integralPart, (int)(fractionalPart * 100 + 0.5)); + (int)integralPart, (int)(fractionalPart * 100)); } /* -------------------------------------------------------------------------- @@ -406,7 +406,7 @@ initHeapProfiling(void) #ifdef PROFILING if (doingLDVProfiling() && doingRetainerProfiling()) { errorBelch("cannot mix -hb and -hr"); - stg_exit(1); + stg_exit(EXIT_FAILURE); } #endif @@ -521,8 +521,6 @@ static void fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length) { char buf[max_length+1], *p, *buf_end; - nat next_offset = 0; - nat written; // MAIN on its own gets printed as "MAIN", otherwise we ignore MAIN. if (ccs == CCS_MAIN) { @@ -554,8 +552,6 @@ fprint_ccs(FILE *fp, CostCentreStack *ccs, nat max_length) if (p >= buf_end) { sprintf(buf+max_length-4, "..."); break; - } else { - next_offset += written; } } fprintf(fp, "%s", buf); @@ -658,6 +654,15 @@ aggregateCensusInfo( void ) int void_total, drag_total; // Now we compute void_total and drag_total for each census + // After the program has finished, the void_total field of + // each census contains the count of words that were *created* + // in this era and were eventually void. Conversely, if a + // void closure was destroyed in this era, it will be + // represented by a negative count of words in void_total. + // + // To get the count of live words that are void at each + // census, just propagate the void_total count forwards: + void_total = 0; drag_total = 0; for (t = 1; t < era; t++) { // note: start at 1, not 0 @@ -665,8 +670,15 @@ 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 ); + // should be true because: void_total is the count of + // live words that are void at this census, which *must* + // be less than the number of live words that have not + // been used yet. + ASSERT( censuses[t].drag_total <= censuses[t].used ); + // similar reasoning as above. } return; @@ -745,15 +757,15 @@ dumpCensus( Census *census ) #ifdef PROFILING if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_LDV) { - fprintf(hp_file, "VOID\t%lu\n", census->void_total * sizeof(W_)); + fprintf(hp_file, "VOID\t%lu\n", (unsigned long)(census->void_total) * sizeof(W_)); fprintf(hp_file, "LAG\t%lu\n", - (census->not_used - census->void_total) * sizeof(W_)); + (unsigned long)(census->not_used - census->void_total) * sizeof(W_)); fprintf(hp_file, "USE\t%lu\n", - (census->used - census->drag_total) * sizeof(W_)); + (unsigned long)(census->used - census->drag_total) * sizeof(W_)); fprintf(hp_file, "INHERENT_USE\t%lu\n", - census->prim * sizeof(W_)); - fprintf(hp_file, "DRAG\t%lu\n", census->drag_total * - sizeof(W_)); + (unsigned long)(census->prim) * sizeof(W_)); + fprintf(hp_file, "DRAG\t%lu\n", + (unsigned long)(census->drag_total) * sizeof(W_)); printSample(rtsFalse, census->time); return; } @@ -831,7 +843,7 @@ dumpCensus( Census *census ) } #endif - fprintf(hp_file, "\t%ld\n", count * sizeof(W_)); + fprintf(hp_file, "\t%lu\n", (unsigned long)count * sizeof(W_)); } printSample(rtsFalse, census->time); @@ -868,9 +880,24 @@ heapCensusChain( Census *census, bdescr *bd ) switch (info->type) { + case THUNK: + size = thunk_sizeW_fromITBL(info); + break; + + case THUNK_1_1: + case THUNK_0_2: + case THUNK_2_0: + size = sizeofW(StgThunkHeader) + 2; + break; + + case THUNK_1_0: + case THUNK_0_1: + case THUNK_SELECTOR: + size = sizeofW(StgThunkHeader) + 1; + break; + case CONSTR: case FUN: - case THUNK: case IND_PERM: case IND_OLDGEN: case IND_OLDGEN_PERM: @@ -878,7 +905,6 @@ heapCensusChain( Census *census, bdescr *bd ) case SE_CAF_BLACKHOLE: case SE_BLACKHOLE: case BLACKHOLE: - case BLACKHOLE_BQ: case CONSTR_INTLIKE: case CONSTR_CHARLIKE: case FUN_1_0: @@ -886,9 +912,6 @@ heapCensusChain( Census *census, bdescr *bd ) case FUN_1_1: case FUN_0_2: case FUN_2_0: - case THUNK_1_1: - case THUNK_0_2: - case THUNK_2_0: case CONSTR_1_0: case CONSTR_0_1: case CONSTR_1_1: @@ -896,7 +919,18 @@ heapCensusChain( Census *census, bdescr *bd ) case CONSTR_2_0: size = sizeW_fromITBL(info); break; - + + case IND: + // Special case/Delicate Hack: INDs don't normally + // appear, since we're doing this heap census right + // after GC. However, GarbageCollect() also does + // resurrectThreads(), which can update some + // blackholes when it calls raiseAsync() on the + // resurrected threads. So we know that any IND will + // be the size of a BLACKHOLE. + size = BLACKHOLE_sizeW(); + break; + case BCO: prim = rtsTrue; size = bco_sizeW((StgBCO *)p); @@ -904,20 +938,17 @@ heapCensusChain( Census *census, bdescr *bd ) case MVAR: case WEAK: - case FOREIGN: case STABLE_NAME: - case MUT_VAR: + case MUT_VAR_CLEAN: + case MUT_VAR_DIRTY: prim = rtsTrue; size = sizeW_fromITBL(info); break; - case THUNK_1_0: /* ToDo - shouldn't be here */ - case THUNK_0_1: /* " ditto " */ - case THUNK_SELECTOR: - size = sizeofW(StgHeader) + MIN_UPD_SIZE; + case AP: + size = ap_sizeW((StgAP *)p); break; - case AP: case PAP: size = pap_sizeW((StgPAP *)p); break; @@ -931,8 +962,10 @@ heapCensusChain( Census *census, bdescr *bd ) size = arr_words_sizeW(stgCast(StgArrWords*,p)); break; - case MUT_ARR_PTRS: + case MUT_ARR_PTRS_CLEAN: + case MUT_ARR_PTRS_DIRTY: case MUT_ARR_PTRS_FROZEN: + case MUT_ARR_PTRS_FROZEN0: prim = rtsTrue; size = mut_arr_ptrs_sizeW((StgMutArrPtrs *)p); break; @@ -953,8 +986,28 @@ heapCensusChain( Census *census, bdescr *bd ) } #endif + case TREC_HEADER: + prim = rtsTrue; + size = sizeofW(StgTRecHeader); + break; + + case TVAR_WAIT_QUEUE: + prim = rtsTrue; + size = sizeofW(StgTVarWaitQueue); + break; + + case TVAR: + prim = rtsTrue; + size = sizeofW(StgTVar); + break; + + case TREC_CHUNK: + prim = rtsTrue; + size = sizeofW(StgTRecChunk); + break; + default: - barf("heapCensus"); + barf("heapCensus, unknown object: %d", info->type); } identity = NULL; @@ -1056,7 +1109,7 @@ heapCensus( void ) // Now traverse the heap in each generation/step. if (RtsFlags.GcFlags.generations == 1) { - heapCensusChain( census, g0s0->to_blocks ); + heapCensusChain( census, g0s0->blocks ); } else { for (g = 0; g < RtsFlags.GcFlags.generations; g++) { for (s = 0; s < generations[g].n_steps; s++) {