X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2FProfiling.c;h=5648f31e00d56613dc21e8e480edd040adda6e8f;hp=4e759b6942a85ba7d618d3ebc01e89e4859a71bb;hb=6cec61d14a324285dbb8ce73d4c7215f1f8d6766;hpb=ed12b7043fa98928f75c289a756fbcef546315f8 diff --git a/rts/Profiling.c b/rts/Profiling.c index 4e759b6..5648f31 100644 --- a/rts/Profiling.c +++ b/rts/Profiling.c @@ -10,15 +10,13 @@ #include "PosixSource.h" #include "Rts.h" + #include "RtsUtils.h" -#include "RtsFlags.h" #include "Profiling.h" #include "Proftimer.h" -#include "Timer.h" #include "ProfHeap.h" #include "Arena.h" #include "RetainerProfile.h" -#include "LdvProfile.h" #include @@ -36,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) @@ -60,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: @@ -123,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 ); @@ -152,41 +152,10 @@ 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; - - /* Register all the cost centres / stacks in the program - * CC_MAIN gets link = 0, all others have non-zero link. - */ - REGISTER_CC(CC_MAIN); - REGISTER_CC(CC_SYSTEM); - REGISTER_CC(CC_GC); - 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 -freeProfiling1 (void) +freeProfiling (void) { arenaFree(prof_arena); } @@ -202,17 +171,36 @@ initProfiling2 (void) * information into it. */ initProfilingLogFile(); + /* Register all the cost centres / stacks in the program + * CC_MAIN gets link = 0, all others have non-zero link. + */ + REGISTER_CC(CC_MAIN); + REGISTER_CC(CC_SYSTEM); + REGISTER_CC(CC_GC); + REGISTER_CC(CC_OVERHEAD); + REGISTER_CC(CC_SUBSUMED); + REGISTER_CC(CC_DONT_CARE); + + REGISTER_CCS(CCS_SYSTEM); + REGISTER_CCS(CCS_GC); + REGISTER_CCS(CCS_OVERHEAD); + REGISTER_CCS(CCS_SUBSUMED); + REGISTER_CCS(CCS_DONT_CARE); + 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; @@ -268,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", 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.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", @@ -641,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"); @@ -665,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) @@ -674,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"); } @@ -687,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) { @@ -710,7 +729,7 @@ reportCCSProfiling( void ) { nat count; char temp[128]; /* sigh: magic constant */ - + stopProfTimer(); total_prof_ticks = 0; @@ -747,7 +766,7 @@ reportCCSProfiling( void ) (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) @@ -759,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; @@ -778,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, @@ -805,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.