update submodules for GHC.HetMet.GArrow -> Control.GArrow renaming
[ghc-hetmet.git] / rts / Profiling.c
index 96a94e4..5648f31 100644 (file)
 
 #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 <string.h>
 
+#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;
+}
 
-  /* Register all the cost centres / stacks in the program 
+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
    * 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., <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", 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 <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", 
@@ -632,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");
@@ -656,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)
@@ -665,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");
   }
@@ -678,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) {
@@ -701,7 +729,7 @@ reportCCSProfiling( void )
 {
     nat count;
     char temp[128]; /* sigh: magic constant */
-
+    
     stopProfTimer();
 
     total_prof_ticks = 0;
@@ -732,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)
@@ -748,12 +778,28 @@ reportCCSProfiling( void )
 
     inherit_costs(CCS_MAIN);
 
-    fprint_header();
-    reportCCS(pruneCCSTree(CCS_MAIN), 0);
+    reportCCS(pruneCCSTree(CCS_MAIN));
+}
+
+static void 
+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 
-reportCCS(CostCentreStack *ccs, nat indent)
+logCCS(CostCentreStack *ccs, nat indent, nat max_label_len, nat max_module_len)
 {
   CostCentre *cc;
   IndexTable *i;
@@ -767,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, 
@@ -794,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.