<> <> <> <> <> <> <> <> <> 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", LookupProperty => "LookupProperty", SetF => "SetF", GetF => "GetF", SetP => "SetP", GetP => "GetP", 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 < IO>> 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 <>