time bug
Matthew Fluet
mfluet@intertrust.com
Wed, 11 Jul 2001 15:02:52 -0700 (PDT)
I got that time bug again. I've given up on stracing self-compiles
(the compiler get < 50% of the CPU time and it's just not worth it).
Anyways, here's the Failure message:
mlton: traceBatch: t' - t::-: t1 = 597.600 t2 = 598.590
And here's all the relevant code; I don't see anything wrong -- anyone
else see something?
*** src/mlton/control/control.sml; structure Control
fun time () =
let
open Time
val {children, self, gc, ...} = times ()
fun add {utime, stime} = utime + stime
in
(add self + add children, add gc)
end
local
fun make(oper, oper_name)
= fn (t1,t2,s)
=> oper(t1, t2)
handle Time => Error.bug (s ^ "::" ^
oper_name ^
": t1 = " ^
(Time.toString t1) ^
" t2 = " ^
(Time.toString t2))
in
val timeMinus = make (Time.-, "-")
val timePlus = make (Time.+, "+")
end
val ('a, 'b) traceBatch: string -> ('a -> 'b) ->
(('a -> 'b) * (unit -> unit)) =
fn name =>
fn f => let
val total = ref Time.zero
val totalGC = ref Time.zero
val verb = Pass
in
(fn a =>
if Verbosity.<= (verb, !verbosity)
then let
val (t, gc) = time ()
fun done () =
let
val (t', gc') = time ()
in
total :=
timePlus (!total,
timeMinus (t',t,
"traceBatch: t' - t"),
"traceBatch: !total");
totalGC :=
timePlus (!totalGC,
timeMinus (gc',gc,
"traceBatch: gc' - gc"),
"traceBatch: !totalGC")
end
in
(f a
before done ())
handle e => (messageStr (verb,
concat [name, " raised"])
; raise e)
end
else f a,
fn () => messageStr (verb,
concat [name,
" totals ",
timeToString {total = !total,
gc = !totalGC}]))
end
***** lib/mlton/basic/time.sml ; structure Time
open Time
fun times (): times =
let
val {self, children, gc} = MLton.Rusage.rusage ()
fun doit ({utime, stime, ...} : MLton.Rusage.t)
= {utime = utime, stime = stime}
in
{self = doit self,
children = doit children,
gc = doit gc}
end
***** basis-library/mlton/rusage.sml ; structure MLton.Rusage
structure Rusage =
struct
open Primitive.MLton.Rusage
type t = {utime: Time.time, stime: Time.time}
fun toTime {sec, usec} =
let
val time_sec = Time.fromSeconds (LargeInt.fromInt sec)
val time_usec = Time.fromMicroseconds (LargeInt.fromInt usec)
in
Time.+ (time_sec, time_usec)
end
fun rusage () =
let val _ = ru ()
in {self = {utime = toTime {sec = self_utime_sec (),
usec = self_utime_usec ()},
stime = toTime {sec = self_stime_sec (),
usec = self_stime_usec ()}},
children = {utime = toTime {sec = children_utime_sec (),
usec = children_utime_usec ()},
stime = toTime {sec = children_stime_sec (),
usec = children_stime_usec ()}},
gc = {utime = toTime {sec = gc_utime_sec (),
usec = gc_utime_usec ()},
stime = toTime {sec = gc_stime_sec (),
usec = gc_stime_usec ()}}}
end
end
***** basis-library/system/Time.sml ; structure Time
datatype time = T of {sec: Int.int, usec: Int.int}
val million: int = 1000000
fun convert (s: LargeInt.int): int =
LargeInt.toInt s handle Overflow => raise Time
fun fromSeconds (s: LargeInt.int): time =
let val s = convert s
in if Primitive.safe andalso s < 0
then raise Time
else T {sec = s, usec = 0}
end
fun fromMicroseconds (s: LargeInt.int): time =
let val s = convert s
in if Primitive.safe andalso s < 0
then raise Time
else T {sec = Int.quot (s, million),
usec = Int.rem (s, million)}
end
val add =
fn (T {sec = s, usec = u}, T {sec = s', usec = u'}) =>
let
val u'' = u + u'
val s'' = s + s'
val (s'', u'') =
if u'' >= million
then (s'' + 1, u'' - million)
else (s'', u'')
in T {sec = s'', usec = u''}
end
val sub =
fn (t1 as T {sec = s, usec = u}, t2 as T {sec = s', usec = u'}) =>
let
val s'' = s - s'
val u'' = u - u'
val (s'', u'') =
if u'' < 0
then (s'' - 1, u'' + million)
else (s'', u'')
in
if s'' < 0
then raise Time
else T {sec = s'', usec = u''}
end
val op + = add
val op - = sub
***** basis-library/misc/primitive.sml ; structure Primitive.MLton.Rusage
structure Rusage =
struct
val ru = _ffi "MLton_Rusage_ru": unit -> unit;
val self_utime_sec = _ffi "MLton_Rusage_self_utime_sec": unit -> int;
val self_utime_usec = _ffi "MLton_Rusage_self_utime_usec": unit -> int;
val self_stime_sec = _ffi "MLton_Rusage_self_stime_sec": unit -> int;
val self_stime_usec = _ffi "MLton_Rusage_self_stime_usec": unit -> int;
val children_utime_sec = _ffi "MLton_Rusage_children_utime_sec": unit -> int;
val children_utime_usec = _ffi "MLton_Rusage_children_utime_usec": unit -> int;
val children_stime_sec = _ffi "MLton_Rusage_children_stime_sec": unit -> int;
val children_stime_usec = _ffi "MLton_Rusage_children_stime_usec": unit -> int;
val gc_utime_sec = _ffi "MLton_Rusage_gc_utime_sec": unit -> int;
val gc_utime_usec = _ffi "MLton_Rusage_gc_utime_usec": unit -> int;
val gc_stime_sec = _ffi "MLton_Rusage_gc_stime_sec": unit -> int;
val gc_stime_usec = _ffi "MLton_Rusage_gc_stime_usec": unit -> int;
end
***** runtime/basis/MLton/rusage.c
#include <sys/resource.h>
#include "gc.h"
#include "mlton-basis.h"
extern struct GC_state gcState;
static struct rusage self;
static struct rusage children;
static struct rusage gc;
Int MLton_Rusage_self_utime_sec() {
return self.ru_utime.tv_sec;
}
Int MLton_Rusage_self_utime_usec() {
return self.ru_utime.tv_usec;
}
Int MLton_Rusage_self_stime_sec() {
return self.ru_stime.tv_sec;
}
Int MLton_Rusage_self_stime_usec() {
return self.ru_stime.tv_usec;
}
Int MLton_Rusage_children_utime_sec() {
return children.ru_utime.tv_sec;
}
Int MLton_Rusage_children_utime_usec() {
return children.ru_utime.tv_usec;
}
Int MLton_Rusage_children_stime_sec() {
return children.ru_stime.tv_sec;
}
Int MLton_Rusage_children_stime_usec() {
return children.ru_stime.tv_usec;
}
Int MLton_Rusage_gc_utime_sec() {
return gc.ru_utime.tv_sec;
}
Int MLton_Rusage_gc_utime_usec() {
return gc.ru_utime.tv_usec;
}
Int MLton_Rusage_gc_stime_sec() {
return gc.ru_stime.tv_sec;
}
Int MLton_Rusage_gc_stime_usec() {
return gc.ru_stime.tv_usec;
}
void MLton_Rusage_ru() {
gc = gcState.ru_gc;
getrusage(RUSAGE_SELF, &self);
getrusage(RUSAGE_CHILDREN, &children);
}