[project @ 1999-03-02 19:50:12 by sof]
[ghc-hetmet.git] / ghc / rts / Stats.c
index 1cbc0ba..c6f7f74 100644 (file)
@@ -1,5 +1,7 @@
 /* -----------------------------------------------------------------------------
- * $Id: Stats.c,v 1.3 1999/01/13 17:25:46 simonm Exp $
+ * $Id: Stats.c,v 1.9 1999/02/23 15:45:08 simonm Exp $
+ *
+ * (c) The GHC Team, 1998-1999
  *
  * Statistics and timing-related functions.
  *
 /* huh? */
 #define BIG_STRING_LEN              512
 
-static StgDouble ElapsedTimeStart = 0.0;
-static StgDouble TicksPerSecond   = 0.0;
+static double ElapsedTimeStart = 0.0;
+static double TicksPerSecond   = 0.0;
 
-static StgDouble InitUserTime = 0.0;
-static StgDouble InitElapsedTime = 0.0;
+static double InitUserTime = 0.0;
+static double InitElapsedTime = 0.0;
 
 static ullong GC_tot_alloc = 0;
+static ullong GC_tot_copied = 0;
 
-static StgDouble GC_start_time,  GC_tot_time = 0;  /* User GC Time */
-static StgDouble GCe_start_time, GCe_tot_time = 0; /* Elapsed GC time */
+static double GC_start_time,  GC_tot_time = 0;  /* User GC Time */
+static double GCe_start_time, GCe_tot_time = 0; /* Elapsed GC time */
 
 lnat MaxResidency = 0;     /* in words; for stats only */
 lnat ResidencySamples = 0; /* for stats only */
 
 static lnat GC_start_faults = 0, GC_end_faults = 0;
 
+static double *GC_coll_times;
+
 /* ToDo: convert this to use integers? --SDM */
 
 /* elapsedtime() -- The current elapsed time in seconds */
 
-StgDouble
+double
 elapsedtime(void)
 {
 #if ! (defined(HAVE_TIMES) || defined(HAVE_FTIME))
@@ -116,7 +121,7 @@ elapsedtime(void)
     struct tms t;
     clock_t r = times(&t);
 
-    return (((StgDouble)r)/TicksPerSecond - ElapsedTimeStart);
+    return (((double)r)/TicksPerSecond - ElapsedTimeStart);
 
 # else /* HAVE_FTIME */
     struct timeb t;
@@ -154,11 +159,11 @@ start_time(void)
        fprintf(stderr, "stat_init: bad call to 'sysconf'!\n");
        stg_exit(EXIT_FAILURE);
     }
-    TicksPerSecond = (StgDouble) ticks;
+    TicksPerSecond = (double) ticks;
 
 #else /* no "sysconf"; had better guess */
 # ifdef HZ
-    TicksPerSecond = (StgDouble) (HZ);
+    TicksPerSecond = (double) (HZ);
 
 # else /* had better guess wildly */
     /* We will #ifdef around the fprintf for machines
@@ -176,16 +181,24 @@ start_time(void)
 void
 initStats(void)
 {
+  nat i;
   FILE *sf = RtsFlags.GcFlags.statsFile;
   
   if (RtsFlags.GcFlags.giveStats) {
     fprintf(sf, "    Alloc    Collect    Live    GC    GC     TOT     TOT  Page Flts\n");
     fprintf(sf, "    bytes     bytes     bytes  user  elap    user    elap\n");
   }
+
+  GC_coll_times = 
+    (double *)stgMallocBytes(sizeof(double) * RtsFlags.GcFlags.generations,
+                          "initStats");
+  for (i = 0; i < RtsFlags.GcFlags.generations; i++) {
+    GC_coll_times[i] = 0.0;
+  }
 }    
 
 
-StgDouble
+double
 usertime(void)
 {
 #if ! (defined(HAVE_GETRUSAGE) || defined(HAVE_TIMES))
@@ -201,7 +214,7 @@ usertime(void)
     struct tms t;
 
     times(&t);
-    return(((StgDouble)(t.tms_utime))/TicksPerSecond);
+    return(((double)(t.tms_utime))/TicksPerSecond);
 
 #else /* HAVE_GETRUSAGE */
     struct rusage t;
@@ -259,13 +272,13 @@ stat_startGC(void)
    -------------------------------------------------------------------------- */
 
 void
-stat_endGC(lnat alloc, lnat collect, lnat live, lnat gen)
+stat_endGC(lnat alloc, lnat collect, lnat live, lnat copied, lnat gen)
 {
     FILE *sf = RtsFlags.GcFlags.statsFile;
 
     if (sf != NULL) {
-       StgDouble time = usertime();
-       StgDouble etime = elapsedtime();
+       double time = usertime();
+       double etime = elapsedtime();
 
        if (RtsFlags.GcFlags.giveStats) {
            nat faults = pagefaults();
@@ -285,9 +298,12 @@ stat_endGC(lnat alloc, lnat collect, lnat live, lnat gen)
            fflush(sf);
        }
 
-       GC_tot_alloc += (ullong) alloc;
-       GC_tot_time  += time-GC_start_time;
-       GCe_tot_time += etime-GCe_start_time;
+       GC_coll_times[gen] += time-GC_start_time;
+
+       GC_tot_copied += (ullong) copied;
+       GC_tot_alloc  += (ullong) alloc;
+       GC_tot_time   += time-GC_start_time;
+       GCe_tot_time  += etime-GCe_start_time;
 
        if (gen == RtsFlags.GcFlags.generations-1) { /* major GC? */
          if (live > MaxResidency) {
@@ -318,9 +334,9 @@ stat_exit(int alloc)
 
     if (sf != NULL){
        char temp[BIG_STRING_LEN];
-       StgDouble time = usertime();
-       StgDouble etime = elapsedtime();
-       StgDouble MutTime, MutElapsedTime;
+       double time = usertime();
+       double etime = elapsedtime();
+       double MutTime, MutElapsedTime;
 
        /* avoid divide by zero if time is measured as 0.00 seconds -- SDM */
        if (time  == 0.0)  time = 0.0001;
@@ -336,6 +352,9 @@ stat_exit(int alloc)
        ullong_format_string(GC_tot_alloc*sizeof(W_), temp, rtsTrue/*commas*/);
        fprintf(sf, "%11s bytes allocated in the heap\n", temp);
 
+       ullong_format_string(GC_tot_copied*sizeof(W_), temp, rtsTrue/*commas*/);
+       fprintf(sf, "%11s bytes copied during GC\n", temp);
+
        if ( ResidencySamples > 0 ) {
            ullong_format_string(MaxResidency*sizeof(W_), temp, rtsTrue/*commas*/);
            fprintf(sf, "%11s bytes maximum residency (%ld sample(s))\n",
@@ -347,8 +366,8 @@ stat_exit(int alloc)
        { /* Count garbage collections */
          nat g;
          for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
-           fprintf(sf, "%11d collections in generation %d\n", 
-                   generations[g].collections, g);
+           fprintf(sf, "%11d collections in generation %d (%6.2fs)\n", 
+                   generations[g].collections, g, GC_coll_times[g]);
          }
        }
        fprintf(sf,"\n%11ld Mb total memory in use\n\n", 
@@ -396,30 +415,38 @@ stat_exit(int alloc)
 void
 stat_describe_gens(void)
 {
-  nat g, s, mut, lge, live;
+  nat g, s, mut, mut_once, lge, live;
   StgMutClosure *m;
   bdescr *bd;
   step *step;
 
-  fprintf(stderr, "     Gen    Steps      Max   Mutable   Step  Blocks     Live    Large\n"       "                    Blocks  Closures                          Objects\n");
+  fprintf(stderr, "     Gen    Steps      Max   Mutable  Mut-Once  Step   Blocks     Live    Large\n                    Blocks  Closures  Closures                         Objects\n");
 
   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
     for (m = generations[g].mut_list, mut = 0; m != END_MUT_LIST; 
         m = m->mut_link) 
       mut++;
-    fprintf(stderr, "%8d %8d %8d %9d", g, generations[g].n_steps,
-           generations[g].max_blocks, mut);
+    for (m = generations[g].mut_once_list, mut_once = 0; m != END_MUT_LIST; 
+        m = m->mut_link) 
+      mut_once++;
+    fprintf(stderr, "%8d %8d %8d %9d %9d", g, generations[g].n_steps,
+           generations[g].max_blocks, mut, mut_once);
 
     for (s = 0; s < generations[g].n_steps; s++) {
       step = &generations[g].steps[s];
       for (bd = step->large_objects, lge = 0; bd; bd = bd->link)
        lge++;
       live = 0;
-      for (bd = step->blocks; bd; bd = bd->link) {
+      if (RtsFlags.GcFlags.generations == 1) {
+       bd = step->to_space;
+      } else {
+       bd = step->blocks;
+      }
+      for (; bd; bd = bd->link) {
        live += (bd->free - bd->start) * sizeof(W_);
       }
       if (s != 0) {
-       fprintf(stderr,"%36s","");
+       fprintf(stderr,"%46s","");
       }
       fprintf(stderr,"%6d %8d %8d %8d\n", s, step->n_blocks,
              live, lge);