DIRECTORY BasicTime USING[GetClockPulses, Now, PulsesToMicroseconds], DBStats, IO, Rope; DBStatsImpl: CEDAR PROGRAM IMPORTS BasicTime, IO, Rope EXPORTS DBStats SHARES DBStats = BEGIN OPEN IO, DBStats; ROPE: TYPE = Rope.ROPE; nGlitches: LONG CARDINAL _ 0; CounterArray: PUBLIC ARRAY CounterEvent OF LONG CARDINAL; TimerWasStarted: REF ARRAY TimerEvent OF BOOLEAN _ NEW[ARRAY TimerEvent OF BOOLEAN]; TimeWhenStarted: REF ARRAY TimerEvent OF LONG CARDINAL _ NEW[ARRAY TimerEvent OF LONG CARDINAL]; NStopTimerCalls: REF ARRAY TimerEvent OF LONG CARDINAL _ NEW[ARRAY TimerEvent OF LONG CARDINAL]; TotalElapsedTime: REF ARRAY TimerEvent OF LONG CARDINAL _ NEW[ARRAY TimerEvent OF LONG CARDINAL]; MaxTime: REF ARRAY TimerEvent OF LONG CARDINAL _ NEW[ARRAY TimerEvent OF LONG CARDINAL]; MinTime: REF ARRAY TimerEvent OF LONG CARDINAL _ NEW[ARRAY TimerEvent OF LONG CARDINAL]; Initialized: BOOLEAN _ FALSE; Initialize: PUBLIC PROC[] = { nGlitches _ 0; CounterArray _ ALL[0]; IF ~Initialized THEN TimerWasStarted^ _ ALL[FALSE]; NStopTimerCalls^ _ ALL[0]; TotalElapsedTime^ _ ALL[0]; MaxTime^ _ ALL[0]; MinTime^ _ ALL[LAST[LONG CARDINAL]]; Initialized _ TRUE; }; StartTimer: PUBLIC PROC[event: TimerEvent] = { IF TimerWasStarted[event] THEN nGlitches _ nGlitches + 1; TimerWasStarted[event] _ TRUE; TimeWhenStarted[event] _ LOOPHOLE[BasicTime.GetClockPulses[]]; }; StopTimer: PUBLIC PROC[event: TimerEvent] = { IF ~TimerWasStarted[event] THEN { nGlitches _ nGlitches + 1; RETURN; }; TimerWasStarted[event] _ FALSE; NStopTimerCalls[event] _ NStopTimerCalls[event] + 1; { elapsedTime: LONG CARDINAL _ LOOPHOLE[BasicTime.GetClockPulses[], LONG CARDINAL] - TimeWhenStarted[event]; TotalElapsedTime[event] _ TotalElapsedTime[event] + elapsedTime; MaxTime[event] _ MAX[elapsedTime, MaxTime[event]]; MinTime[event] _ MIN[elapsedTime, MinTime[event]]; }; }; AbortTimer: PUBLIC PROC[event: TimerEvent] = { TimerWasStarted[event] _ FALSE; }; EnumerateCounters: PROC[procToApply: PROC[CounterEvent]] = { FOR p: CounterEvent IN CounterEvent DO procToApply[p] ENDLOOP; }; EnumerateTimers: PROC[procToApply: PROC[TimerEvent]] = { FOR p: TimerEvent IN TimerEvent DO procToApply[p] ENDLOOP; }; Print: PUBLIC PROC[ heading: ROPE, out: IO.STREAM, verbose: BOOLEAN] = { PrintHighResolutionTime: PROC[time: LONG CARDINAL] RETURNS[BOOLEAN] = { time _ LOOPHOLE[BasicTime.PulsesToMicroseconds[LOOPHOLE[time]],LONG CARDINAL]/100; {ms: LONG CARDINAL _ time/10; decimal: LONG CARDINAL _ time MOD 10; out.PutF["%g.%g", card[ms], card[decimal]]; RETURN[ms <= 1]}; }; PrintCounter: PROC[e: CounterEvent] = { IF CounterArray[e] > 0 THEN { out.PutF[" %g: %g events\n", rope[PNameOfCounterEvent[e]], card[CounterArray[e]]] } ELSE IF verbose THEN { out.PutF[" %g: no events\n", rope[PNameOfCounterEvent[e]]] }; }; PrintTimer: PROC[e: TimerEvent] = { IF NStopTimerCalls[e] > 0 THEN { timeIsSmall: BOOLEAN; out.PutF[" %g: ", rope[PNameOfTimerEvent[e]]]; timeIsSmall _ PrintHighResolutionTime[TotalElapsedTime[e]/NStopTimerCalls[e]]; IF timeIsSmall THEN { avgTime: CARDINAL _ BasicTime.PulsesToMicroseconds[LOOPHOLE[TotalElapsedTime[e]/NStopTimerCalls[e]]]; out.PutF[" ms (%g us) average time for %g events.", card[avgTime], card[NStopTimerCalls[e]]];} ELSE out.PutF[" ms average time for %g events.", card[NStopTimerCalls[e]]]; out.PutF[" Max = "]; [] _ PrintHighResolutionTime[MaxTime[e]]; out.PutF[", Min = "]; [] _ PrintHighResolutionTime[MinTime[e]]; out.PutF[".\n"] } ELSE IF verbose THEN { out.PutF[" %g: no events\n", rope[PNameOfTimerEvent[e]]] }; }; currentTime: LONG CARDINAL _ LOOPHOLE[BasicTime.Now[]]; IF heading = NIL OR heading.Length[] = 0 THEN heading _ "DBStats"; out.PutF[IF verbose THEN "%g (printing all events at %g)\n" ELSE "%g (printing nonzero events at %g)\n", IO.rope[heading], IO.time[]]; EnumerateCounters[PrintCounter]; EnumerateTimers[PrintTimer]; IF nGlitches > 0 THEN out.PutF["Note: %g out of order calls to Starting or Stopping\n", card[nGlitches]]; nGlitches _ 0; out.PutF["\n\n"]; out.Flush[]; --force stream if necessary }; PNameOfCounterEvent: PROC[event: CounterEvent] RETURNS[ROPE] = { RETURN[SELECT event FROM CacheReadOrWrite => "CacheReadOrWrite", CacheHTLookup => "CacheHTLookup", CacheHTConflictInLookup => "CacheHTConflictInLookup", CacheMiss => "CacheMiss", CacheWritePageBack => "CacheWritePageBack", SegmentAllocPage => "SegmentAllocPage", SegmentFreePage => "SegmentFreePage", StorageCreateTuple => "StorageCreateTuple", StorageCreateSystemTuple => "StorageCreateSystemTuple", StorageDestroyTuple => "StorageDestroyTuple", StorageReadTupleset => "StorageReadTupleset", StorageReadField => "StorageReadField", StorageWriteField => "StorageWriteField", StorageInitVecPage => "StorageInitVecPage", StorageCheckVecPage => "StorageCheckVecPage", StorageAllocVec => "StorageAllocVec", StorageFreeVec => "StorageFreeVec", StorageModifyVec => "StorageModifyVec", StorageModifyDifficultVec => "StorageModifyDifficultVec", StorageCompactPage => "StorageCompactPage", DBIndexInsert => "DBIndexInsert", DBIndexDelete => "DBIndexDelete", DBIndexOpenScan => "DBIndexOpenScan", DBIndexNextScan => "DBIndexNextScan", DBIndexBiggerKey => "DBIndexBiggerKey", DBIndexEqualKey => "DBIndexEqualKey", BTreeSearchPage => "BTreeSearchPage", BTreeSwapInPage => "BTreeSwapInPage", BTreeSwapOutPage => "BTreeSwapOutPage", ENDCASE => "Don't know" ] }; PNameOfTimerEvent: PUBLIC PROC[event: TimerEvent] RETURNS[ROPE] = { RETURN[SELECT event FROM AlpineFileCreateTransaction => "AlpineFileCreateTransaction", AlpineFileFinishTransaction => "AlpineFileFinishTransaction", AlpineFileOpen => "AlpineFileOpen", AlpineFileReadPage => "AlpineFileReadPage", AlpineFileWritePage => "AlpineFileWritePage", AlpineFileGetSize => "AlpineFileGetSize", AlpineFileSetSize =>"AlpineFileSetSize", OpenTransaction => "OpenTransaction", CloseTransaction => "CloseTransaction", MarkTransaction => "MarkTransaction", AbortTransaction => "AbortTransaction", DeclareDomain => "DeclareDomain", LookupDomain => "LookupDomain", DestroyDomain => "DestroyDomain", DeclareRelation => "DeclareRelation", LookupRelation => "LookupRelation", DestroyRelation => "DestroyRelation", DeclareEntity => "DeclareEntity", LookupEntity => "LookupEntity", DestroyEntity => "DestroyEntity", DeclareIndex => "DeclareIndex", DestroyIndex => "DestroyIndex", CreateRelship => "CreateRelship", LookupRelship => "LookupRelship", DestroyRelship => "DestroyRelship", SetF => "SetF", GetF => "GetF", EntityInfo => "EntityInfo", RelationSubset => "RelationSubset", NextRelship => "NextRelship", PrevRelship => "PrevRelship", DomainSubset => "DomainSubset", NextEntity => "NextEntity", PrevEntity => "PrevEntity", ENDCASE => "Don't know" ] }; END. -- DBStatsImpl CHANGE LOG Created by MBrown on February 26, 1981 10:21 AM Changed by MBrown on 1-Mar-81 11:47:23 Changed by Cattell on 15-Dec-81 10:23:31 Changed by Cattell on April 29, 1982 10:03 pm Changed by Willie-Sue on June 24, 1982 12:02 pm Changed by Cattell on October 11, 1982 4:22 pm Changed by wert on August 13, 1984 2:07:27 am PDT Changed by Willie-Sue on February 15, 1985 File DBStatsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by: MBrown on 1-Mar-81 11:48:15 Cattell on October 28, 1983 2:30 pm Willie-Sue on February 15, 1985 11:13:13 am PST Last Edited by: Wert, August 13, 1984 2:08:53 am PDT Donahue, February 28, 1986 2:24:15 pm PST Widom, August 26, 1985 10:52:29 am PDT Module state Counts number of poorly-matched Starting - Stopping calls. Only the following structures are a function of the data gathered by StopTimer. Procedures (see also the inlines in DBStats). Don't wipe out timer events in progress, please. Called by DBStats.Starting. Called by DBStats.Stopping. What is done next is a function of how elaborate the stats need to be. It might even be a function of event. For now, do something simple. Called by DBStats.Aborting. Aborts timing of this event. Returns TRUE iff time is less than 2 ms. convert to 1/10 ms units DBFile-- Pilot version created by editing PerfStatsImpl. Left out a few necessary things, like PNameOfTimerEvent, etc. Converted to IOStream. Added DBView items. IOStream => IO Added some timer events. Changed the *n (BCPL new line) to \n (cedar newline) in the formatted output strings. This makes the DB.Statistics file easier to read... made Cedar, added tioga formatting Κ˜šœ™Jšœ Οmœ1™<—šœ™Jšœ™Jšœ#™#Jšœ/™/Jšœ4™4Icode™)J™&—J˜šΟk ˜ Jšœ žœ,˜;J˜Jšžœ˜J˜J˜—šœ žœž˜šž˜Jšœ žœ˜—J˜šž˜J˜—J˜šž˜J˜—J˜Jšœžœžœžœ ˜J˜Jšžœžœžœ˜head1šœ ™ šœ žœžœ˜Jšœ:™:J˜—Jš œžœžœžœžœžœ˜9š œžœžœ žœžœ˜2Jšžœžœ žœžœ˜!—š œžœžœ žœžœžœ˜8Jš žœžœ žœžœžœ˜'—š œžœžœ žœžœžœ˜8Jš žœžœ žœžœžœ˜'J˜—JšœP™Pš œžœžœ žœžœžœ˜9Jš žœžœ žœžœžœ˜'—š œ žœžœ žœžœžœ˜0Jš žœžœ žœžœžœ˜'—š œ žœžœ žœžœžœ˜0Jš žœžœ žœžœžœ˜'——šœ-™-Jšœ žœžœ˜J˜šΟn œžœžœ˜Jšœ0™0J˜Jšœžœ˜Jšžœžœžœžœ˜3Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jš œ žœžœžœžœ˜$Jšœžœ˜J˜——˜šŸ œžœžœ˜.Jšœ™Jšžœžœ˜9Jšœžœ˜Jšœžœ˜>J˜——˜šŸ œžœžœ˜-Jšœ™šžœžœ˜!J˜Jšžœ˜J˜—Jšœžœ˜J˜4JšœP™PJšœ;™;˜Jš œ žœžœžœžœžœ˜jJ˜@Jšœžœ˜2Jšœžœ˜2J˜—J˜——˜šŸ œžœžœ˜.Jšœ9™9Jšœžœ˜J˜——˜šŸœžœžœ˜J˜——˜šŸœžœžœ˜8Jšžœžœ žœžœ˜:J˜——˜šŸœžœžœ žœžœžœ žœ˜Hš Ÿœžœžœžœžœžœ˜GJšœ(™(š œžœ žœžœžœ˜RJšœ™Jšœžœžœ ˜Jšœ žœžœžœ˜%J˜+Jšžœ ˜J˜—šŸ œžœ˜'šžœžœ˜J˜T—Jšžœžœ žœA˜UJ˜—šŸ œžœ˜#šžœžœ˜ Jšœ žœ˜J˜/J˜Nšžœ žœ˜šœ žœ˜Jšœžœ+˜R—J˜^—šž˜J˜F—J˜J˜)J˜J˜)J˜—Jšžœžœ žœ?˜SJ˜—Jšœ žœžœžœ˜7Jšžœ žœžœžœ˜Bšœ žœ žœ$˜