<> <> <> 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 = { <> 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. <<>> <> <> <<>> <<>> <<>>