ComputeWorkingSet.mesa
Robert Hagmann February 21, 1984 7:46:57 am PST
Bob Hagmann November 13, 1985 8:40:51 am PST
DIRECTORY
BasicTime USING [GetClockPulses, Pulses, PulsesToMicroseconds],
Commander USING [CommandProc, Handle, Register],
CommandTool USING [ArgumentVector, Failed, Parse],
Convert USING[ Error, IntFromRope ],
IO,
Process USING[ Pause, Seconds, SecondsToTicks ],
VMInternal;
ComputeWorkingSet: CEDAR PROGRAM
IMPORTS BasicTime, Commander, CommandTool, Convert, IO, Process, VMInternal
SHARES VMInternal =
BEGIN
OPEN VMInternal;
ComputeWorkingSet: Commander.CommandProc = {
PROC [cmd: Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL]
size: INT = lastRealPage;
delay: Process.Seconds ← 5;
argv: CommandTool.ArgumentVector;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GO TO Usage; }];
IF argv.argc > 2 THEN RETURN[$Failure, "Wrong number of arguments"];
IF argv.argc = 2 THEN {
delay ← Convert.IntFromRope[argv[1] ! Convert.Error => GOTO Usage];
IF delay <= 0 THEN GOTO Usage;
};
DO
pinned: INT ← 0;
free: INT ← 0;
readonly: INT ← 0;
readonlyrefd: INT ← 0;
rwdirty: INT ← 0;
rwdirtyrefd: INT ← 0;
rwclean: INT ← 0;
rwcleanrefd: INT ← 0;
unmapped: INT ← 0;
page: INT ← RealPageNumber.FIRST;
totalpages: INT ← 0 ;
startPulse: BasicTime.Pulses = BasicTime.GetClockPulses[];
endPulse: BasicTime.Pulses;
microsecs: LONG CARDINAL ;
TRUSTED {
WHILE page <= size DO
totalpages ← totalpages.SUCC;
WITH rmMap[page] SELECT FROM
rmE: reclaimable RMMapEntry => {
vP: PageNumber = rmE.virtual;
vmEntry: VMMapEntry = GetVMMap[vP];
WITH vmE: vmEntry SELECT InOut[vmEntry] FROM
in => {
refed: BOOL = vmE.state.flags.referenced;
dirty: BOOL = vmE.state.flags.dirty OR rmE.needsBackingStoreWrite;
IF vmE.state.flags.readonly THEN {
IF refed THEN readonlyrefd ← readonlyrefd.SUCC
ELSE readonly ← readonly.SUCC;
}
ELSE {
IF dirty THEN {
IF refed THEN rwdirtyrefd ← rwdirtyrefd.SUCC
ELSE rwdirty ← rwdirty.SUCC;
}
ELSE {
IF refed THEN rwcleanrefd ← rwcleanrefd.SUCC
ELSE rwclean ← rwclean.SUCC;
};
};
IF refed THEN [] ← Age[vP ];};
out => {
unmapped ← unmapped.SUCC; -- probably being swapped in
};
ENDCASE;
};
rmE: free RMMapEntry => {
free ← free.SUCC ;
};
rmE: pinned RMMapEntry => {
pinned ← pinned.SUCC;
};
ENDCASE;
page ← page.SUCC;
ENDLOOP;
};
endPulse ← BasicTime.GetClockPulses[];
microsecs ← BasicTime.PulsesToMicroseconds[endPulse-startPulse];
IO.PutF[cmd.out, "\n Millisecs for stats %g free: %g pinned: %g unmapped: %g\n", IO.card[microsecs/1000], IO.int[free], IO.int[pinned], IO.int[unmapped]];
IO.PutF[cmd.out, " readonly: %g readonlyrefd: %g rwdirty: %g rwdirtyrefd: %g\n", IO.int[readonly], IO.int[readonlyrefd], IO.int[rwdirty], IO.int[rwdirtyrefd]];
IO.PutF[cmd.out, " rwclean: %g rwcleanrefd: %g total pages: %g\n", IO.int[rwclean], IO.int[rwcleanrefd], IO.int[totalpages]];
IO.PutF[cmd.out, " Totals -- refed %g unrefed: %g refed+pinned %g\n", IO.int[readonlyrefd+rwdirtyrefd+rwcleanrefd], IO.int[readonly+rwdirty+rwclean], IO.int[readonlyrefd+rwdirtyrefd+rwcleanrefd+pinned]];
Process.Pause[Process.SecondsToTicks[delay]];
ENDLOOP;
EXITS
Usage => RETURN[$Failure, "Usage: ComputeWorkingSet {seconds ← 5} "];
};
Commander.Register[key: "ComputeWorkingSet", proc: ComputeWorkingSet,
doc: "ComputeWorkingSet {seconds ← 5} — turn off referenced bits, wait for seconds, print statistics, and loop. Stop by the STOP! button"];
END.
Bob Hagmann November 13, 1985 8:33:26 am PST
make pretty for CedarChest