X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FProfiling.c;h=5648f31e00d56613dc21e8e480edd040adda6e8f;hb=cd47700887365ca2a6af17d03e731efce65cf2ac;hp=0bb975cafc8a0828945b278c1dd557f44a884ebf;hpb=3f10646cfe2c3409056a49d1ef1c4507af522573;p=ghc-hetmet.git diff --git a/rts/Profiling.c b/rts/Profiling.c index 0bb975c..5648f31 100644 --- a/rts/Profiling.c +++ b/rts/Profiling.c @@ -10,19 +10,20 @@ #include "PosixSource.h" #include "Rts.h" + #include "RtsUtils.h" -#include "RtsFlags.h" #include "Profiling.h" -#include "Storage.h" #include "Proftimer.h" -#include "Timer.h" #include "ProfHeap.h" #include "Arena.h" #include "RetainerProfile.h" -#include "LdvProfile.h" #include +#ifdef DEBUG +#include "Trace.h" +#endif + /* * Profiling allocation arena. */ @@ -33,13 +34,13 @@ Arena *prof_arena; * closure_cats */ -unsigned int CC_ID; -unsigned int CCS_ID; -unsigned int HP_ID; +unsigned int CC_ID = 1; +unsigned int CCS_ID = 1; +unsigned int HP_ID = 1; /* figures for the profiling report. */ -static ullong total_alloc; +static StgWord64 total_alloc; static lnat total_prof_ticks; /* Globals for opening the profiling log file(s) @@ -57,8 +58,8 @@ CostCentreStack *CCCS; /* Linked lists to keep track of cc's and ccs's that haven't * been declared in the log file yet */ -CostCentre *CC_LIST; -CostCentreStack *CCS_LIST; +CostCentre *CC_LIST = NULL; +CostCentreStack *CCS_LIST = NULL; /* * Built-in cost centres and cost-centre stacks: @@ -120,7 +121,9 @@ static CostCentreStack * ActualPush_ ( CostCentreStack *ccs, CostCentre *cc 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 findCCSMaxLens ( CostCentreStack *ccs, nat indent, nat *max_label_len, nat *max_module_len ); +static void logCCS ( CostCentreStack *ccs, nat indent, nat max_label_len, nat max_module_len ); +static void reportCCS ( CostCentreStack *ccs ); static void DecCCS ( CostCentreStack *ccs ); static void DecBackEdge ( CostCentreStack *ccs, CostCentreStack *oldccs ); @@ -149,17 +152,26 @@ initProfiling1 (void) /* for the benefit of allocate()... */ CCCS = CCS_SYSTEM; - - /* Initialize counters for IDs */ - CC_ID = 1; - CCS_ID = 1; - HP_ID = 1; - - /* Initialize Declaration lists to NULL */ - CC_LIST = NULL; - CCS_LIST = NULL; +} + +void +freeProfiling (void) +{ + arenaFree(prof_arena); +} + +void +initProfiling2 (void) +{ + CostCentreStack *ccs, *next; + + CCCS = CCS_SYSTEM; + + /* Set up the log file, and dump the header and cost centre + * information into it. */ + initProfilingLogFile(); - /* Register all the cost centres / stacks in the program + /* Register all the cost centres / stacks in the program * CC_MAIN gets link = 0, all others have non-zero link. */ REGISTER_CC(CC_MAIN); @@ -168,42 +180,27 @@ initProfiling1 (void) REGISTER_CC(CC_OVERHEAD); REGISTER_CC(CC_SUBSUMED); 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_DONT_CARE); - - CCCS = CCS_OVERHEAD; - - /* 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. */ - initProfilingLogFile(); + REGISTER_CCS(CCS_MAIN); /* find all the "special" cost centre stacks, and make them children * of CCS_MAIN. */ - ASSERT(CCS_MAIN->prevStack == 0); + ASSERT(CCS_LIST == CCS_MAIN); + CCS_LIST = CCS_LIST->prevStack; + CCS_MAIN->prevStack = NULL; CCS_MAIN->root = CC_MAIN; ccsSetSelected(CCS_MAIN); DecCCS(CCS_MAIN); - for (ccs = CCS_LIST; ccs != CCS_MAIN; ) { + for (ccs = CCS_LIST; ccs != NULL; ) { next = ccs->prevStack; - ccs->prevStack = 0; + ccs->prevStack = NULL; ActualPush_(CCS_MAIN,ccs->cc,ccs); ccs->root = ccs->cc; ccs = next; @@ -259,41 +256,66 @@ ccsSetSelected( CostCentreStack *ccs ) static void initProfilingLogFile(void) { - /* Initialise the log file name */ - prof_filename = arenaAlloc(prof_arena, strlen(prog_name) + 6); - sprintf(prof_filename, "%s.prof", prog_name); - - /* open the log file */ - if ((prof_file = fopen(prof_filename, "w")) == NULL) { - debugBelch("Can't open profiling report file %s\n", prof_filename); - RtsFlags.CcFlags.doCostCentres = 0; - // The following line was added by Sung; retainer/LDV profiling may need - // two output files, i.e., .prof/hp. - if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) - RtsFlags.ProfFlags.doHeapProfile = 0; - return; + char *prog; + + prog = arenaAlloc(prof_arena, strlen(prog_name) + 1); + 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.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 %ld \"%s\" \"%s\"\n", - CC_UQ, cc->ccID, cc->label, cc->module); - } - } + if (RtsFlags.CcFlags.doCostCentres == 0 && + RtsFlags.ProfFlags.doHeapProfile != HEAP_BY_RETAINER) + { + /* No need for the .prof file */ + prof_filename = NULL; + prof_file = NULL; + } + else + { + /* Initialise the log file name */ + prof_filename = arenaAlloc(prof_arena, strlen(prog) + 6); + sprintf(prof_filename, "%s.prof", prog); + + /* open the log file */ + if ((prof_file = fopen(prof_filename, "w")) == NULL) { + debugBelch("Can't open profiling report file %s\n", prof_filename); + RtsFlags.CcFlags.doCostCentres = 0; + // The following line was added by Sung; retainer/LDV profiling may need + // two output files, i.e., .prof/hp. + if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) + RtsFlags.ProfFlags.doHeapProfile = 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", RtsFlags.MiscFlags.tickInterval); + + /* declare all the cost centres */ + { + CostCentre *cc; + for (cc = CC_LIST; cc != NULL; cc = cc->link) { + fprintf(prof_file, "%d %ld \"%s\" \"%s\"\n", + CC_UQ, cc->ccID, cc->label, cc->module); + } + } + } } if (RtsFlags.ProfFlags.doHeapProfile) { /* Initialise the log file name */ - hp_filename = arenaAlloc(prof_arena, strlen(prog_name) + 6); - sprintf(hp_filename, "%s.hp", prog_name); - + hp_filename = arenaAlloc(prof_arena, strlen(prog) + 6); + sprintf(hp_filename, "%s.hp", prog); + /* open the log file */ if ((hp_file = fopen(hp_filename, "w")) == NULL) { debugBelch("Can't open profiling report file %s\n", @@ -353,11 +375,12 @@ CostCentreStack * PushCostCentre ( CostCentreStack *ccs, CostCentre *cc ) #define PushCostCentre _PushCostCentre { - IF_DEBUG(prof, - debugBelch("Pushing %s on ", cc->label); - debugCCS(ccs); - debugBelch("\n")); - return PushCostCentre(ccs,cc); + IF_DEBUG(prof, + traceBegin("pushing %s on ", cc->label); + debugCCS(ccs); + traceEnd();); + + return PushCostCentre(ccs,cc); } #endif @@ -631,20 +654,26 @@ static void report_per_cc_costs( void ) { CostCentre *cc, *next; + nat max_label_len, max_module_len; aggregate_cc_costs(CCS_MAIN); sorted_cc_list = NULL; + max_label_len = max_module_len = 0; + for (cc = CC_LIST; cc != NULL; cc = next) { next = cc->link; if (cc->time_ticks > total_prof_ticks/100 || cc->mem_alloc > total_alloc/100 || RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_ALL) { insert_cc_in_sorted_list(cc); + + max_label_len = stg_max(strlen(cc->label), max_label_len); + max_module_len = stg_max(strlen(cc->module), max_module_len); } } - fprintf(prof_file, "%-30s %-20s", "COST CENTRE", "MODULE"); + fprintf(prof_file, "%-*s %-*s", max_label_len, "COST CENTRE", max_module_len, "MODULE"); fprintf(prof_file, "%6s %6s", "%time", "%alloc"); if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) { fprintf(prof_file, " %5s %9s", "ticks", "bytes"); @@ -655,7 +684,7 @@ report_per_cc_costs( void ) if (cc_to_ignore(cc)) { continue; } - fprintf(prof_file, "%-30s %-20s", cc->label, cc->module); + fprintf(prof_file, "%-*s %-*s", max_label_len, cc->label, max_module_len, cc->module); fprintf(prof_file, "%6.1f %6.1f", total_prof_ticks == 0 ? 0.0 : (cc->time_ticks / (StgFloat) total_prof_ticks * 100), total_alloc == 0 ? 0.0 : (cc->mem_alloc / (StgFloat) @@ -664,7 +693,7 @@ report_per_cc_costs( void ) if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) { fprintf(prof_file, " %5" FMT_Word64 " %9" FMT_Word64, - (StgWord64)(cc->time_ticks), cc->mem_alloc); + (StgWord64)(cc->time_ticks), cc->mem_alloc*sizeof(W_)); } fprintf(prof_file, "\n"); } @@ -677,11 +706,11 @@ report_per_cc_costs( void ) -------------------------------------------------------------------------- */ static void -fprint_header( void ) +fprint_header( nat max_label_len, nat max_module_len ) { fprintf(prof_file, "%-24s %-10s individual inherited\n", "", ""); - fprintf(prof_file, "%-24s %-50s", "COST CENTRE", "MODULE"); + fprintf(prof_file, "%-*s %-*s", max_label_len, "COST CENTRE", max_module_len, "MODULE"); fprintf(prof_file, "%6s %10s %5s %5s %5s %5s", "no.", "entries", "%time", "%alloc", "%time", "%alloc"); if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) { @@ -700,7 +729,7 @@ reportCCSProfiling( void ) { nat count; char temp[128]; /* sigh: magic constant */ - + stopProfTimer(); total_prof_ticks = 0; @@ -731,11 +760,13 @@ reportCCSProfiling( void ) fprintf(prof_file, "\n\n"); fprintf(prof_file, "\ttotal time = %11.2f secs (%lu ticks @ %d ms)\n", - total_prof_ticks / (StgFloat) TICK_FREQUENCY, - total_prof_ticks, TICK_MILLISECS); + (double) total_prof_ticks * + (double) RtsFlags.MiscFlags.tickInterval / 1000, + (unsigned long) total_prof_ticks, + (int) RtsFlags.MiscFlags.tickInterval); fprintf(prof_file, "\ttotal alloc = %11s bytes", - ullong_format_string(total_alloc * sizeof(W_), + showStgWord64(total_alloc * sizeof(W_), temp, rtsTrue/*commas*/)); #if defined(PROFILING_DETAIL_COUNTS) @@ -747,12 +778,28 @@ reportCCSProfiling( void ) inherit_costs(CCS_MAIN); - fprint_header(); - reportCCS(pruneCCSTree(CCS_MAIN), 0); + reportCCS(pruneCCSTree(CCS_MAIN)); } static void -reportCCS(CostCentreStack *ccs, nat indent) +findCCSMaxLens(CostCentreStack *ccs, nat indent, nat *max_label_len, nat *max_module_len) { + CostCentre *cc; + IndexTable *i; + + cc = ccs->cc; + + *max_label_len = stg_max(*max_label_len, indent + strlen(cc->label)); + *max_module_len = stg_max(*max_module_len, strlen(cc->module)); + + for (i = ccs->indexTable; i != 0; i = i->next) { + if (!i->back_edge) { + findCCSMaxLens(i->ccs, indent+1, max_label_len, max_module_len); + } + } +} + +static void +logCCS(CostCentreStack *ccs, nat indent, nat max_label_len, nat max_module_len) { CostCentre *cc; IndexTable *i; @@ -766,8 +813,8 @@ reportCCS(CostCentreStack *ccs, nat indent) /* force printing of *all* cost centres if -P -P */ { - fprintf(prof_file, "%-*s%-*s %-50s", - indent, "", 24-indent, cc->label, cc->module); + fprintf(prof_file, "%-*s%-*s %-*s", + indent, "", max_label_len-indent, cc->label, max_module_len, cc->module); fprintf(prof_file, "%6ld %11.0f %5.1f %5.1f %5.1f %5.1f", ccs->ccsID, (double) ccs->scc_count, @@ -793,11 +840,23 @@ reportCCS(CostCentreStack *ccs, nat indent) for (i = ccs->indexTable; i != 0; i = i->next) { if (!i->back_edge) { - reportCCS(i->ccs, indent+1); + logCCS(i->ccs, indent+1, max_label_len, max_module_len); } } } +static void +reportCCS(CostCentreStack *ccs) +{ + nat max_label_len, max_module_len; + max_label_len = max_module_len = 0; + + findCCSMaxLens(ccs, 0, &max_label_len, &max_module_len); + + fprint_header(max_label_len, max_module_len); + logCCS(ccs, 0, max_label_len, max_module_len); +} + /* Traverse the cost centre stack tree and accumulate * ticks/allocations. @@ -881,8 +940,6 @@ gen_XML_logfile( void ) reportCCS_XML(pruneCCSTree(CCS_MAIN)); fprintf(prof_file, " 0\n"); - - fclose(prof_file); } static void