#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 <string.h>
* 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)
/* 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:
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 );
/* 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);
}
* 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;
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., <program>.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 <prog>.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., <program>.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",
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");
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)
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");
}
-------------------------------------------------------------------------- */
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) {
{
nat count;
char temp[128]; /* sigh: magic constant */
-
+
stopProfTimer();
total_prof_ticks = 0;
(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)
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;
/* 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,
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.