/* -----------------------------------------------------------------------------
- * $Id: Stats.c,v 1.4 1999/02/02 14:21:32 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))
struct tms t;
clock_t r = times(&t);
- return (((StgDouble)r)/TicksPerSecond - ElapsedTimeStart);
+ return (((double)r)/TicksPerSecond - ElapsedTimeStart);
# else /* HAVE_FTIME */
struct timeb t;
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
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))
struct tms t;
times(&t);
- return(((StgDouble)(t.tms_utime))/TicksPerSecond);
+ return(((double)(t.tms_utime))/TicksPerSecond);
#else /* HAVE_GETRUSAGE */
struct rusage t;
-------------------------------------------------------------------------- */
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();
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) {
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;
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",
{ /* 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",
bdescr *bd;
step *step;
- fprintf(stderr, " Gen Steps Max Mutable Mut-Once Step Blocks Live Large\n Blocks Closures 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;
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 %8d", g, generations[g].n_steps,
+ 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++) {
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);