profiling

Matthew Fluet Matthew Fluet <fluet@CS.Cornell.EDU>
Thu, 19 Apr 2001 11:12:34 -0400 (EDT)


> If you want to work on any of the other outstanding bugs (times, size,
> self-compile) feel free.  I'm still a week or so from having any time.

I've reimplemented timing in the following way:

1. added  struct rusage ru_gc  to   struct GC_State  in gc.h
   removed  uint recentStart  from  struct GC_State  in gc.h

2. modified gc.c to update ru_gc appropriately (i.e., perform
   getrusage(RUSAGE_SELF, &ru_start) just before the gc, perform
   getrusage(RUSAGE_SELF, &ru_finish) just after the gc,
   and set  ru_gc = ru_gc + (ru_finish - ru_start),
   where I've defined appropriate rusagePlus and rusageMinus functions).
   So, we now record all resource usage of the garbage collector, not just
   time.  The gcTime is still there and updated during a gc, but it will
   (almost) always correspond to the time derived from the data in ru_gc.
   (There might be some rounding cases where they will differ, but it
   should be negligible; and we could avoid it by always resetting gcTime
   to the time derived from ru_gc, rather than incrementing it with the
   time derived from (ru_finish - ru_start).)

3. added /src/runtime/basis/MLton/rusage.c
   The function MLton_RUsage_ru will atomically record the rusage for
   SELF, CHILDREN and the GC as follows:

static struct rusage self;
static struct rusage children;
static struct rusage gc;

void MLton_RUsage_ru() {
  gc = gcState.ru_gc;
  getrusage(RUSAGE_SELF, &self);
  getrusage(RUSAGE_CHILDREN, &children);
}

   Then there are a series of accessors to pull the data out.

4. added /src/basis-library/mlton/rusage.{sig,sml}

signature MLTON_RUSAGE =
   sig
      type timeval = {sec: int, usec: int}
      val toTime: timeval -> Time.time
      type rusage = {utime: timeval, stime: timeval}
      val rusage: unit -> {self: rusage, children: rusage, gc: rusage}
   end

   So, right now, I'm only pulling out the user and system time, but we
   can easily add more accessors if we want other info.  The
   implementation of rusage is the obvious one: make the FFI call to
   MLton_RUsage_ru and then run through the accessors.

   Note that we don't need to worry about intervening GC calls any more.
   Successive calls to MLton.RUsage.rusage will have self' >= self,
   children' >= children, and gc' >= gc, and (self' - self) >= (gc' - gc).

5. modified /src/basis-library/mlton/mlton.{sig,sml} to have the RUsage
   structure.

6. modified /src/lib/mlton/basic/time.{sig,sml} to use
   MLton.RUsage.rusage.  It converts the {sec usec} record into a
   Time.time and will ditch any extra fields in the rusage that we might
   add later
   modified /src/lib/mlton/basic/{process,trace}.sml to use the new type
   of Time.times
   modified /src/mlton/control/control.sml to use the new type of
   Time.times; in particular, we don't need pre and post versions any
   more.

7. modified /src/basis-library/posix/proc-env.sml to revert
   Posix.ProcEnv.times back to it's original definition.

8. modified /src/mlton/codegen/x86-codegen/x86-mlton.fun
   to reflect change in offset of gcState.canHandle

And I think that's it.  I'm running regressions and benchmarks now, and
I'll run a self-compile, regressions, and benchmarks tonight on a faster
machine.  But, let me know if there are any objections/modifications to
the changes outlined above.