<> <> DIRECTORY BasicTime, DifferenceAveragers, IO, Labels, Menus, MJSContainers, Real, RealFns, Rope, Rules, SafeStorage, VFonts, ViewerClasses, ViewerOps; MemoryMonitor: CEDAR PROGRAM IMPORTS DifferenceAveragers, IO, Labels, MJSContainers, Real, RealFns, Rules, SafeStorage, VFonts, ViewerOps = BEGIN ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; Time: TYPE = BasicTime.GMT; Averager: TYPE = DifferenceAveragers.Averager; ViewerList: TYPE = LIST OF Viewer; IntList: TYPE = LIST OF INT; XRange: TYPE = DifferenceAveragers.XRange; Seconds: TYPE = INT; Monitor: TYPE = REF MonitorPrivate; MonitorPrivate: TYPE = RECORD [ labelBot, labelTop: BOOL, halfLives: IntList, container: Viewer _ NIL, parts: PartList _ NIL, ticks, labels: ViewerList _ NIL, spLoc, hlLoc, barLoc: XRange _ [0, 0], tickSpacing, bot, top: INTEGER _ 0, initialized: BOOL _ FALSE ]; PartList: TYPE = LIST OF Part; Part: TYPE = REF PartPrivate; PartPrivate: TYPE = RECORD [ averager: Averager ]; Sample: TYPE = REF SamplePrivate; SamplePrivate: TYPE = RECORD [ allocated, reclaimed: INT ]; monitorFlavor: ATOM = $MemoryMonitor; monitorClass: MJSContainers.MJSContainerClass = NEW [MJSContainers.MJSContainerClassRep _ [ adjust: Adjust]]; logMin: INT = 0; logMax: INT = 5; font: VFonts.Font = VFonts.defaultFont; tickHeight: INT = 3; sep0: INT = tickHeight + 1; fudge1: INT = 5; sep3: INT = VFonts.FontHeight[] + fudge1; sep1: INT = sep3 + sep0; fudge2: INT _ 6; sep2: INT _ 1; Adjust: PROC [self: Viewer] RETURNS [adjusted: BOOL _ FALSE] --ViewerClasses.AdjustProc-- = { m: Monitor = NARROW[MJSContainers.GetClientData[self]]; IF m # NIL AND m.initialized THEN { SetLayout[m]; adjusted _ TRUE; }; }; SampleMemoryUsage: PROC [clientData: REF ANY] RETURNS [add, subtract: REAL] = { s: Sample = NARROW[clientData]; allocated: INT = SafeStorage.NWordsAllocated[]; reclaimed: INT = SafeStorage.NWordsReclaimed[]; add _ allocated - s.allocated; subtract _ reclaimed - s.reclaimed; s.allocated _ allocated; s.reclaimed _ reclaimed; }; Create: PROC [halfLives: IntList, viewerInfo: ViewerClasses.ViewerRec _ [], labelBot, labelTop: BOOL _ TRUE] RETURNS [m: Monitor] = { m _ NEW [MonitorPrivate _ [ labelBot: labelBot, labelTop: labelTop, halfLives: halfLives ]]; viewerInfo.data _ m; m.container _ MJSContainers.Create[monitorFlavor, viewerInfo]; Init[m.container]; }; Init: PROC [self: Viewer] = { m: Monitor = NARROW[MJSContainers.GetClientData[self]]; dy: INT = VFonts.FontHeight[] + fudge2; y: INT _ IF m.labelTop THEN sep1 ELSE 0; AddButtonLabels: PROC [by: INT] = { spl: Viewer = Labels.Create[info: [wx: m.spLoc.left, wy: by, parent: m.container, name: "sample t", border: FALSE], paint: FALSE]; hll: Viewer = Labels.Create[info: [wx: m.hlLoc.left, wy: by, parent: m.container, name: "1/2 life", border: FALSE], paint: FALSE]; }; m.top _ y; FOR hll: IntList _ m.halfLives, hll.rest WHILE hll # NIL DO halfLife: INT = hll.first; s: Sample = NEW [SamplePrivate _ [ SafeStorage.NWordsAllocated[], SafeStorage.NWordsReclaimed[] ]]; a: Averager = DifferenceAveragers.Create[ viewerInfo: [parent: m.container, wx: 0, wy: y, ww: m.container.cw, wh: dy, border: FALSE, scrollable: FALSE], samplePeriod: 1, halfLife: halfLife, logMin: logMin, logMax: logMax, Sample: SampleMemoryUsage, clientData: s]; v: Viewer = a.AsViewer[]; p: Part = NEW [PartPrivate _ [a]]; MJSContainers.ChildXBound[m.container, v]; [] _ MJSContainers.FlushChildX[v]; m.parts _ CONS[p, m.parts]; y _ v.wy + v.wh; IF hll.rest # NIL THEN y _ y + sep2; ENDLOOP; m.bot _ y; [m.spLoc, m.hlLoc, m.barLoc] _ DifferenceAveragers.GetLayout[m.parts.first.averager, m.container]; IF m.labelTop THEN AddButtonLabels[0]; IF m.labelBot THEN {AddButtonLabels[y]; y _ y + sep1}; FOR log: INT DECREASING IN [logMin .. logMax] DO x: INT = (log - logMin) * m.tickSpacing + m.barLoc.left; AddOne: PROC [ty, ly: INT] = { tick: Viewer = Rules.Create[info: [wx: x, wy: ty, ww: 1, wh: tickHeight, parent: m.container], paint: FALSE]; exp: REAL = RealFns.Power[10, log]; label: Viewer = Labels.Create[info: [wx: x, wy: ly, parent: m.container, name: IF log < 0 THEN IO.PutFR["%g", [real[exp]]] ELSE IO.PutFR["%g", [integer[Real.Round[exp]]]], border: FALSE], paint: FALSE]; m.ticks _ CONS[tick, m.ticks]; m.labels _ CONS[label, m.labels]; }; IF m.labelTop THEN AddOne[m.top-tickHeight, m.top-sep1]; IF m.labelBot THEN AddOne[m.bot, m.bot + sep0]; ENDLOOP; SetLayout[m]; ViewerOps.SetOpenHeight[m.container, y]; m.initialized _ TRUE; IF NOT m.container.iconic THEN ViewerOps.ComputeColumn[m.container.column]; }; SetLayout: PROC [m: Monitor] = { av: Viewer = m.parts.first.averager.AsViewer[]; ticks: ViewerList _ m.ticks; labels: ViewerList _ m.labels; x: INTEGER; [] _ MJSContainers.FlushChildX[m.parts.first.averager.AsViewer[]]; m.barLoc _ m.parts.first.averager.GetLayout[m.container].bars; m.tickSpacing _ m.barLoc.width/(logMax - logMin); x _ m.barLoc.left; FOR log: INT IN [logMin .. logMax] DO DoIt: PROC [ty, ly: INT] = { tick: Viewer = ticks.first; label: Viewer = labels.first; ViewerOps.MoveViewer[tick, x, ty, 1, tickHeight, FALSE]; ViewerOps.MoveViewer[label, x - (log - logMin)*label.ww/(logMax-logMin), ly, label.ww, label.wh, FALSE]; ticks _ ticks.rest; labels _ labels.rest; }; IF m.labelBot THEN DoIt[m.bot, m.bot + sep0]; IF m.labelTop THEN DoIt[m.top-tickHeight, m.top-sep1]; x _ x + m.tickSpacing; ENDLOOP; }; Start: PROC = { MJSContainers.RegisterClass[monitorFlavor, monitorClass]; }; Start[]; END.