MemoryMonitor.Mesa
Spreitzer, June 17, 1986 3:15:07 pm PDT
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: BOOLFALSE
];
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: BOOLFALSE] --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: BOOLTRUE] 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: INTIF 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.