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.  ComputeWorkingSet.mesa Robert Hagmann February 21, 1984 7:46:57 am PST Bob Hagmann November 13, 1985 8:40:51 am PST PROC [cmd: Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] Bob Hagmann November 13, 1985 8:33:26 am PST make pretty for CedarChest ÊB˜Jšœ™šœ0™0Icode™,—J˜šÏk ˜ Jšœ œ0˜?Jšœ œ!˜0Jšœ œ!˜2Jšœœ˜$Jšœ˜Jšœœ#˜0Jšœ ˜ —J˜šœœ˜ Jšœ"œœ˜KJšœ ˜—J˜Jš˜Jšœ ˜J˜J˜J˜šÏbœ˜,Jš œœ œœ œœ™DIcode0šœœ˜Lšœ˜Lšœ!˜!JšœHœœ ˜XJšœœœ(˜Dšœœ˜Jšœ7œ˜CJšœ œœ˜J˜—š˜Lšœœ˜Lšœœ˜Lšœ œ˜Lšœœ˜Lšœ œ˜Lšœ œ˜Lšœ œ˜Lšœ œ˜Lšœ œ˜Lšœœœ˜!Lšœ œ˜Lšœ:˜:Lšœ˜Lšœ œœ˜šœ˜ šœ˜Lšœœ˜šœ œ˜šœ ˜ Lšœ˜Jšœ#˜#šœœ˜,˜Jšœœ˜)Jšœœœ˜Bšœœ˜"Jš œœœœœ˜MJ˜—šœœ˜šœœ˜Jš œœœœœ˜IJ˜—šœœ˜Jš œœœœœ˜IJ˜—J˜—Jšœœ˜—šœ˜JšœœÏc˜7J˜—Jšœ˜—L˜—šœ˜Lšœ œ˜L˜—šœ˜Lšœœ˜L˜—Lšœ˜—Lšœ œ˜Lšœ˜——L˜Lšœ&˜&Lšœ@˜@Lš œRœœ œœ˜Lš œRœœœœ˜¢LšœEœœœ˜LšœGœ,œ œ3˜ÎLšœ-˜-Lšœ˜—š˜Kšœ œ6˜E—L˜—L˜JšœÒ˜ÒJ˜Jšœ˜K™™,KšÏr™—K™K™K™—…— ’à