DIRECTORY Atom, BasicTime, GGStatistics, IO, Rope; GGStatisticsImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, IO EXPORTS GGStatistics = BEGIN Table: TYPE = REF TableObj; TableObj: TYPE = GGStatistics.TableObj; Interval: TYPE = REF IntervalObj; IntervalObj: TYPE = GGStatistics.IntervalObj; gTableList: LIST OF Table; Init: PROC [] = { gTableList _ NIL; [] _ CreateTable[$Gargoyle]; }; CreateTable: PUBLIC PROC [name: ATOM] RETURNS [table: Table] = { oldTable: Table; table _ NEW[TableObj _ [NIL, name]]; oldTable _ GetTable[name]; IF oldTable = NIL THEN gTableList _ CONS[table, gTableList] ELSE oldTable.intervals _ NIL; }; GetTable: PUBLIC PROC [name: ATOM] RETURNS [table: Table] = { FOR list: LIST OF Table _ gTableList, list.rest UNTIL list = NIL DO IF list.first.name = name THEN RETURN[list.first]; ENDLOOP; RETURN[NIL]; }; ResetTable: PUBLIC PROC [table: Table] = { FOR list: LIST OF Interval _ table.intervals, list.rest UNTIL list = NIL DO ResetIntervalInternal[list.first]; ENDLOOP; }; CreateInterval: PUBLIC PROC [name: ATOM, subintervals: LIST OF Interval _ NIL] RETURNS [interval: Interval] = { interval _ NEW[IntervalObj _ [name: name, subintervals: subintervals, starts: 0, stops: 0, unmatchedStarts: 0, startTime: 0, totalTime: 0, maxTime: 0, maxIndex: 9999, minTime: LAST[LONG CARDINAL]]]; }; ResetIntervalInternal: PROC [interval: Interval] = { FOR list: LIST OF Interval _ interval.subintervals, list.rest UNTIL list = NIL DO ResetIntervalInternal[list.first]; ENDLOOP; interval.starts _ 0; interval.stops _ 0; interval.unmatchedStarts _ 0; interval.startTime _ 0; interval.totalTime _ 0; interval.maxTime _ 0; interval.minTime _ LAST[LONG CARDINAL] }; AddInterval: PUBLIC PROC [interval: Interval, table: Table] = { table.intervals _ CONS[interval, table.intervals]; }; AddInt: PUBLIC PROC [interval: Interval, tableName: ATOM] = { AddInterval[interval, GetTable[tableName]]; }; FindInterval: PROC [name: ATOM, table: Table] RETURNS [Interval] = { sub: Interval; success: BOOL; FOR list: LIST OF Interval _ table.intervals, list.rest UNTIL list = NIL DO [sub, success] _ FindSubInterval[name, list.first]; IF success THEN RETURN[sub]; ENDLOOP; SIGNAL Problem[msg: "No such interval in this table."]; RETURN[NIL]; }; FindSubInterval: PROC [name: ATOM, interval: Interval] RETURNS [sub: Interval, success: BOOL] = { IF interval.name = name THEN RETURN[interval, TRUE]; FOR subList: LIST OF Interval _ interval.subintervals, subList.rest UNTIL subList = NIL DO [sub, success] _ FindSubInterval[name, subList.first]; IF success THEN RETURN; ENDLOOP; RETURN[NIL, FALSE]; }; StartInterval: PUBLIC PROC [name: ATOM, table: Table] = { interval: Interval _ FindInterval[name, table]; IF interval.starts >= interval.stops + 1 THEN { interval.starts _ interval.stops; interval.unmatchedStarts _ interval.unmatchedStarts + 1; }; interval.starts _ interval.starts + 1; interval.startTime _ BasicTime.GetClockPulses[]; }; StartInt: PUBLIC PROC [intervalName: ATOM, tableName: ATOM] = { StartInterval[intervalName, GetTable[tableName]]; }; StopInterval: PUBLIC PROC [name: ATOM, table: Table] = { interval: Interval; stopTime, elapsedTime: BasicTime.Pulses; stopTime _ BasicTime.GetClockPulses[]; interval _ FindInterval[name, table]; interval.stops _ interval.stops + 1; elapsedTime _ stopTime - interval.startTime; interval.totalTime _ interval.totalTime + elapsedTime; interval.minTime _ IF elapsedTime < interval.minTime THEN elapsedTime ELSE interval.minTime; IF elapsedTime > interval.maxTime THEN { interval.maxTime _ elapsedTime; interval.maxIndex _ interval.starts; }; }; StopInt: PUBLIC PROC [intervalName: ATOM, tableName: ATOM] = { StopInterval[intervalName, GetTable[tableName]]; }; PrintInterval: PROC [f: IO.STREAM, interval: Interval, nestingLevel: NAT _ 0] = { name: Rope.ROPE; totalTime, avgTime, minTime, maxTime: LONG CARDINAL; IF interval.starts # 0 THEN { FOR i: NAT IN [1..nestingLevel] DO f.PutChar[IO.TAB]; ENDLOOP; name _ Atom.GetPName[interval.name]; totalTime _ BasicTime.PulsesToMicroseconds[interval.totalTime]/1000; f.PutF["%g. starts: %g. total: %g. ", [rope[name]], [integer[interval.starts]], [integer[totalTime]]]; avgTime _ totalTime/interval.starts; minTime _ BasicTime.PulsesToMicroseconds[interval.minTime]/1000; maxTime _ BasicTime.PulsesToMicroseconds[interval.maxTime]/1000; f.PutF["avg: %g. min: %g. max: %g, index: %g, overflows: %g\n", [integer[avgTime]], [integer[minTime]], [integer[maxTime]], [integer[interval.maxIndex]], [integer[interval.unmatchedStarts]]]; FOR children: LIST OF Interval _ interval.subintervals, children.rest UNTIL children = NIL DO PrintInterval[f, children.first, nestingLevel+1]; ENDLOOP; }; }; PrintTable: PUBLIC PROC [f: IO.STREAM, table: Table] = { FOR list: LIST OF Interval _ table.intervals, list.rest UNTIL list = NIL DO PrintInterval[f, list.first, 0]; ENDLOOP; }; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; Init[]; END. nGGStatisticsImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last edited by Bier on June 18, 1986 Contents: Routines for maintaining a table of average times for user-specified operations. Getting ready to test performance. Testing performance. Printing results. PrintInterval: PROC [f: IO.STREAM, interval: Interval, nestingLevel: NAT _ 0] = { name: Rope.ROPE; totalTime, avgTime, minTime, maxTime: LONG CARDINAL; IF interval.starts # 0 THEN { FOR i: NAT IN [1..nestingLevel] DO Feedback.AppendTypescript[NIL, " ", begin]; -- print a Tab on the typescript ENDLOOP; name _ Atom.GetPName[interval.name]; totalTime _ BasicTime.PulsesToMicroseconds[interval.totalTime]/1000; Feedback.PutFTypescript[NIL, middle, "%g. starts: %g. total: %g. ", [rope[name]], [integer[interval.starts]], [integer[totalTime]]]; avgTime _ totalTime/interval.starts; minTime _ BasicTime.PulsesToMicroseconds[interval.minTime]/1000; maxTime _ BasicTime.PulsesToMicroseconds[interval.maxTime]/1000; Feedback.PutFTypescript[NIL, end, "avg: %g. min: %g. max: %g, index: %g, overflows: %g", [integer[avgTime]], [integer[minTime]], [integer[maxTime]], [integer[interval.maxIndex]], [integer[interval.unmatchedStarts]]]; FOR children: LIST OF Interval _ interval.subintervals, children.rest UNTIL children = NIL DO PrintInterval[f, children.first, nestingLevel+1]; ENDLOOP; }; }; Κn˜J˜Icodešœ™Kšœ Οmœ1™Kšœ0˜0K˜K™—K™K™K˜š Ÿ œžœžœžœ$žœ ˜QKšœ žœ˜Kšœ&žœžœ˜4šžœžœ˜šžœžœžœž˜"Kšœ žœžœ˜Kšžœ˜—Kšœ$˜$KšœD˜DKšœi˜iKšœ$˜$Kšœ@˜@Kšœ@˜@KšœΑ˜Αš žœ žœžœ1žœ žœž˜]Kšœ1˜1Kšžœ˜—K˜—K˜K˜—š Ÿ œžœžœžœ$žœ ™QKšœ žœ™Kšœ&žœžœ™4šžœžœ™šžœžœžœž™"KšœžœΟc ™LKšžœ™—Kšœ$™$KšœD™DKšœžœl™‡Kšœ$™$Kšœ@™@Kšœ@™@KšœžœΏ™Ϊš žœ žœžœ1žœ žœž™]Kšœ1™1Kšžœ™—K™—K™K™—š Ÿ œžœžœžœžœ˜8š žœžœžœ'žœžœž˜KKšœ ˜ Kšžœ˜—K˜K˜—Kš Ÿœžœžœ žœžœ˜/K˜˜K˜—Kšžœ˜J˜—…—P ,