[project @ 2000-04-24 22:05:08 by panne]
[ghc-hetmet.git] / ghc / rts / Profiling.c
index fd5dc92..fe2c6e8 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Profiling.c,v 1.15 2000/03/07 11:53:12 simonmar Exp $
+ * $Id: Profiling.c,v 1.19 2000/04/19 12:42:48 simonmar Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -12,9 +12,7 @@
 #include "Rts.h"
 #include "RtsUtils.h"
 #include "RtsFlags.h"
-#include "ProfRts.h"
-#include "StgRun.h"
-#include "StgStartup.h"
+#include "Profiling.h"
 #include "Storage.h"
 #include "Proftimer.h"
 #include "Itimer.h"
@@ -48,11 +46,14 @@ rtsBool time_profiling = rtsFalse;
  */
 static lnat total_alloc, total_prof_ticks;
 
-/* Globals for opening the profiling log file
+/* Globals for opening the profiling log file(s)
  */
 static char *prof_filename; /* prof report file name = <program>.prof */
 FILE *prof_file;
 
+static char *hp_filename;      /* heap profile (hp2ps style) log file */
+FILE *hp_file;
+
 /* The Current Cost Centre Stack (for attributing costs)
  */
 CostCentreStack *CCCS;
@@ -83,25 +84,26 @@ CostCentreStack *CCS_LIST;
  *    SUBSUMED is the one-and-only CCS placed on top-level functions. 
  *           It indicates that all costs are to be attributed to the
  *           enclosing cost centre stack.  SUBSUMED never accumulates
- *           any costs.
+ *           any costs.  The is_caf flag is set on the subsumed cost
+ *           centre.
  *
  *    DONT_CARE is a placeholder cost-centre we assign to static
  *           constructors.  It should *never* accumulate any costs.
  */
 
-CC_DECLARE(CC_MAIN,      "MAIN",       "MAIN",      "MAIN",  CC_IS_BORING,);
-CC_DECLARE(CC_SYSTEM,    "SYSTEM",     "MAIN",      "MAIN",  CC_IS_BORING,);
-CC_DECLARE(CC_GC,        "GC",         "GC",        "GC",    CC_IS_BORING,);
-CC_DECLARE(CC_OVERHEAD,  "OVERHEAD_of", "PROFILING", "PROFILING", CC_IS_CAF,);
-CC_DECLARE(CC_SUBSUMED,  "SUBSUMED",    "MAIN",      "MAIN",  CC_IS_SUBSUMED,);
-CC_DECLARE(CC_DONTZuCARE,"DONT_CARE",   "MAIN",      "MAIN",  CC_IS_BORING,);
+CC_DECLARE(CC_MAIN,      "MAIN",       "MAIN",      CC_IS_BORING, );
+CC_DECLARE(CC_SYSTEM,    "SYSTEM",     "MAIN",      CC_IS_BORING, );
+CC_DECLARE(CC_GC,        "GC",         "GC",        CC_IS_BORING, );
+CC_DECLARE(CC_OVERHEAD,  "OVERHEAD_of", "PROFILING", CC_IS_CAF,    );
+CC_DECLARE(CC_SUBSUMED,  "SUBSUMED",    "MAIN",      CC_IS_CAF,    );
+CC_DECLARE(CC_DONT_CARE, "DONT_CARE",   "MAIN",      CC_IS_BORING, );
 
-CCS_DECLARE(CCS_MAIN,      CC_MAIN,       CC_IS_BORING,   );
-CCS_DECLARE(CCS_SYSTEM,            CC_SYSTEM,     CC_IS_BORING,   );
-CCS_DECLARE(CCS_GC,         CC_GC,         CC_IS_BORING,   );
-CCS_DECLARE(CCS_OVERHEAD,   CC_OVERHEAD,   CC_IS_CAF,      );
-CCS_DECLARE(CCS_SUBSUMED,   CC_SUBSUMED,   CC_IS_SUBSUMED, );
-CCS_DECLARE(CCS_DONTZuCARE, CC_DONTZuCARE, CC_IS_BORING,   );
+CCS_DECLARE(CCS_MAIN,      CC_MAIN,       );
+CCS_DECLARE(CCS_SYSTEM,            CC_SYSTEM,     );
+CCS_DECLARE(CCS_GC,         CC_GC,         );
+CCS_DECLARE(CCS_OVERHEAD,   CC_OVERHEAD,   );
+CCS_DECLARE(CCS_SUBSUMED,   CC_SUBSUMED,   );
+CCS_DECLARE(CCS_DONT_CARE,  CC_DONT_CARE, );
 
 /* 
  * Uniques for the XML log-file format
@@ -120,7 +122,6 @@ CCS_DECLARE(CCS_DONTZuCARE, CC_DONTZuCARE, CC_IS_BORING,   );
 static CostCentreStack * ActualPush_ ( CostCentreStack *ccs, CostCentre *cc, 
                                       CostCentreStack *new_ccs );
 
-static    void registerCostCentres ( void );
 static rtsBool ccs_to_ignore       ( CostCentreStack *ccs );
 static    void count_ticks         ( CostCentreStack *ccs );
 static    void reportCCS           ( CostCentreStack *ccs, nat indent );
@@ -147,13 +148,11 @@ static    void reportCCS_XML       ( CostCentreStack *ccs );
    -------------------------------------------------------------------------- */
 
 void
-initProfiling (void)
+initProfiling1 (void)
 {
-  CostCentreStack *ccs, *next;
-
   /* for the benefit of allocate()... */
   CCCS = CCS_SYSTEM;
-
+  
   /* Initialize counters for IDs */
   CC_ID  = 1;
   CCS_ID = 1;
@@ -171,21 +170,30 @@ initProfiling (void)
   REGISTER_CC(CC_GC);
   REGISTER_CC(CC_OVERHEAD);
   REGISTER_CC(CC_SUBSUMED);
-  REGISTER_CC(CC_DONTZuCARE);
+  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_DONTZuCARE);
+  REGISTER_CCS(CCS_DONT_CARE);
 
   CCCS = CCS_OVERHEAD;
-  registerCostCentres();
+
+  /* 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.
-   */
+   * information into it.  */
   initProfilingLogFile();
 
   /* find all the "special" cost centre stacks, and make them children
@@ -214,31 +222,45 @@ initProfiling (void)
 static void
 initProfilingLogFile(void)
 {
-  /* Initialise the log file name */
-  prof_filename = stgMallocBytes(strlen(prog_argv[0]) + 6, "initProfiling");
-  sprintf(prof_filename, "%s.prof", prog_argv[0]);
-
-  /* open the log file */
-  if ((prof_file = fopen(prof_filename, "w")) == NULL) {
-    fprintf(stderr, "Can't open profiling report file %s\n", prof_filename);
-    RtsFlags.CcFlags.doCostCentres = 0;
-    return;
-  }
+    /* Initialise the log file name */
+    prof_filename = stgMallocBytes(strlen(prog_argv[0]) + 6, "initProfiling");
+    sprintf(prof_filename, "%s.prof", prog_argv[0]);
+
+    /* open the log file */
+    if ((prof_file = fopen(prof_filename, "w")) == NULL) {
+       fprintf(stderr, "Can't open profiling report file %s\n", prof_filename);
+       RtsFlags.CcFlags.doCostCentres = 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", TICK_MILLISECS);
+    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 %d \"%s\" \"%s\"\n",
+                       CC_UQ, cc->ccID, cc->label, cc->module);
+           }
+       }
+    }
     
-    /* declare all the cost centres */
-    {
-      CostCentre *cc;
-      for (cc = CC_LIST; cc != NULL; cc = cc->link) {
-       fprintf(prof_file, "%d %d \"%s\" \"%s\" \"%s\"\n",
-               CC_UQ, cc->ccID, cc->label, cc->module, cc->group);
-      }
+    if (RtsFlags.ProfFlags.doHeapProfile) {
+       /* Initialise the log file name */
+       hp_filename = stgMallocBytes(strlen(prog_argv[0]) + 6, "initProfiling");
+       sprintf(hp_filename, "%s.hp", prog_argv[0]);
+       
+       /* open the log file */
+       if ((hp_file = fopen(hp_filename, "w")) == NULL) {
+           fprintf(stderr, "Can't open profiling report file %s\n", 
+                   hp_filename);
+           RtsFlags.ProfFlags.doHeapProfile = 0;
+           return;
+       }
     }
-  }
 }
 
 void
@@ -262,47 +284,7 @@ endProfiling ( void )
 }
 
 /* -----------------------------------------------------------------------------
-   Register Cost Centres
-
-   At the moment, this process just supplies a unique integer to each
-   statically declared cost centre and cost centre stack in the
-   program.
-
-   The code generator inserts a small function "reg<moddule>" in each
-   module which registers any cost centres from that module and calls
-   the registration functions in each of the modules it imports.  So,
-   if we call "regMain", each reachable module in the program will be
-   registered. 
-
-   The reg* functions are compiled in the same way as STG code,
-   i.e. without normal C call/return conventions.  Hence we must use
-   StgRun to call this stuff.
-   -------------------------------------------------------------------------- */
-
-/* The registration functions use an explicit stack... 
- */
-#define REGISTER_STACK_SIZE  (BLOCK_SIZE * 4)
-F_ *register_stack;
-
-static void
-registerCostCentres ( void )
-{
-  /* this storage will be reclaimed by the garbage collector,
-   * as a large block.
-   */
-  register_stack = (F_ *)allocate(REGISTER_STACK_SIZE / sizeof(W_));
-
-  StgRun((StgFunPtr)stg_register, &MainRegTable);
-}
-
-
-/* -----------------------------------------------------------------------------
-   Set cost centre stack when entering a function.  Here we implement
-   the rule
-
-      "if CCSfn is an initial segment of CCCS, 
-          then set CCCS to CCSfn,
-         else append CCSfn to CCCS"
+   Set cost centre stack when entering a function.
    -------------------------------------------------------------------------- */
 rtsBool entering_PAP;
 
@@ -315,10 +297,10 @@ EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn )
     return CCCS;
   }
 
-  if (cccs->root == ccsfn->root) {
-    return ccsfn;
-  } else {
+  if (ccsfn->root->is_caf == CC_IS_CAF) {
     return AppendCCS(cccs,ccsfn);
+  } else {
+    return ccsfn;
   }
 }
 
@@ -413,7 +395,7 @@ AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 )
     return ccs1;
   }
 
-  if (ccs2->cc->is_subsumed != CC_IS_BORING) {
+  if (ccs2->cc->is_caf == CC_IS_CAF) {
     return ccs1;
   }
   
@@ -515,11 +497,9 @@ print_ccs (FILE *fp, CostCentreStack *ccs)
   if (ccs != CCS_MAIN)
     {
       print_ccs(fp, ccs->prevStack);
-      fprintf(fp, "->[%s,%s,%s]", 
-             ccs->cc->label, ccs->cc->module, ccs->cc->group);
+      fprintf(fp, "->[%s,%s]", ccs->cc->label, ccs->cc->module);
     } else {
-      fprintf(fp, "[%s,%s,%s]", 
-             ccs->cc->label, ccs->cc->module, ccs->cc->group);
+      fprintf(fp, "[%s,%s]", ccs->cc->label, ccs->cc->module);
     }
       
   if (ccs == CCCS) {
@@ -647,11 +627,6 @@ fprint_header( void )
 {
   fprintf(prof_file, "%-24s %-10s", "COST CENTRE", "MODULE");  
 
-#ifdef NOT_YET
-  do_groups = have_interesting_groups(Registered_CC);
-  if (do_groups) fprintf(prof_file, " %-11.11s", "GROUP");
-#endif
-
   fprintf(prof_file, "%8s %5s %5s %8s %5s", "scc", "%time", "%alloc", "inner", "cafs");
 
   if (RtsFlags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE) {
@@ -670,9 +645,6 @@ report_ccs_profiling( void )
 {
     nat count;
     char temp[128]; /* sigh: magic constant */
-#ifdef NOT_YET
-    rtsBool do_groups = rtsFalse;
-#endif
 
     stopProfTimer();
 
@@ -742,10 +714,6 @@ reportCCS(CostCentreStack *ccs, nat indent)
     fprintf(prof_file, "%-*s%-*s %-10s", 
            indent, "", 24-indent, cc->label, cc->module);
 
-#ifdef NOT_YET
-    if (do_groups) fprintf(prof_file, " %-11.11s",cc->group);
-#endif
-
     fprintf(prof_file, "%8ld %5.1f %5.1f %8ld %5ld",
            ccs->scc_count, 
            total_prof_ticks == 0 ? 0.0 : (ccs->time_ticks / (StgFloat) total_prof_ticks * 100),
@@ -798,7 +766,7 @@ static rtsBool
 ccs_to_ignore (CostCentreStack *ccs)
 {
     if (    ccs == CCS_OVERHEAD 
-        || ccs == CCS_DONTZuCARE
+        || ccs == CCS_DONT_CARE
         || ccs == CCS_GC 
         || ccs == CCS_SYSTEM) {
        return rtsTrue;
@@ -865,6 +833,8 @@ reportCCS_XML(CostCentreStack *ccs)
   CostCentre *cc;
   IndexTable *i;
 
+  if (ccs_to_ignore(ccs)) { return; }
+
   cc = ccs->cc;
   
   fprintf(prof_file, " 1 %d %lu %lu %lu",