-- File DBStatsImpl.mesa
-- Last edited by:
-- MBrown on 1-Mar-81 11:48:15
-- Cattell on March 14, 1983 2:11 pm
-- Willie-Sue on June 24, 1982 12:02 pm
DIRECTORY
DBStats,
Inline USING[LowHalf],
IO,
Rope,
System USING[GetClockPulses, GetGreenwichMeanTime, PulsesToMicroseconds],
String USING [AppendString];
DBStatsImpl: PROGRAM
IMPORTS
IO,
I: Inline,
Rope,
String,
System
EXPORTS
DBStats
SHARES
DBStats
= BEGIN OPEN IO, DBStats;
-- Module state
nGlitches: LONG CARDINAL ← 0;
-- Counts number of poorly-matched Starting - Stopping calls.
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];
-- Only the following structures are a function of the data gathered by StopTimer.
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];
-- Procedures (see also the inlines in DBStats).
Initialized: BOOLEAN ← FALSE;
Initialize: PUBLIC PROC[] = {
-- Don't wipe out timer events in progress, please.
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] = {
-- Called by DBStats.Starting.
IF TimerWasStarted[event] THEN nGlitches ← nGlitches + 1;
TimerWasStarted[event] ← TRUE;
TimeWhenStarted[event] ← LOOPHOLE[System.GetClockPulses[]];
};
StopTimer: PUBLIC PROC[event: TimerEvent] = {
-- Called by DBStats.Stopping.
IF ~TimerWasStarted[event] THEN {
nGlitches ← nGlitches + 1;
RETURN;
};
TimerWasStarted[event] ← FALSE;
NStopTimerCalls[event] ← NStopTimerCalls[event] + 1;
-- 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.
{
elapsedTime: LONG CARDINAL ← LOOPHOLE[System.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] = {
-- Called by DBStats.Aborting. Aborts timing of this event.
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.Handle, verbose: BOOLEAN] = {
PrintHighResolutionTime: PROC[time: LONG CARDINAL] RETURNS[BOOLEAN] = {
-- Returns TRUE iff time is less than 2 ms.
time ← LOOPHOLE[System.PulsesToMicroseconds[LOOPHOLE[time]],LONG CARDINAL]/100;
-- convert to 1/10 ms units
{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", string[PNameOfCounterEvent[e]], card[CounterArray[e]]] }
ELSE IF verbose THEN { out.PutF[" %g: no events*n", string[PNameOfCounterEvent[e]]] };
};
PrintTimer: PROC[e: TimerEvent] = {
IF NStopTimerCalls[e] > 0 THEN {
timeIsSmall: BOOLEAN;
out.PutF[" %g: ", string[PNameOfTimerEvent[e]]];
timeIsSmall ← PrintHighResolutionTime[TotalElapsedTime[e]/NStopTimerCalls[e]];
IF timeIsSmall THEN {
avgTime: CARDINAL ←
I.LowHalf[System.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", string[PNameOfTimerEvent[e]]] };
};
currentTime: LONG CARDINAL ← LOOPHOLE[System.GetGreenwichMeanTime[]];
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
};
-- This stuff will soon be provided by Cedar RTTypes; watch this space...
pName: STRING ← [40];
PNameOfCounterEvent: PUBLIC PROC[event: CounterEvent] RETURNS[LONG STRING] = {
pName.length ← 0;
String.AppendString[to: pName, from: SELECT event FROM
CacheReadOrWrite => "CacheReadOrWrite"L,
CacheHTLookup => "CacheHTLookup"L,
CacheHTConflictInLookup => "CacheHTConflictInLookup"L,
CacheMiss => "CacheMiss"L,
CacheWritePageBack => "CacheWritePageBack"L,
SegmentAllocPage => "SegmentAllocPage"L,
SegmentFreePage => "SegmentFreePage"L,
StorageCreateTuple => "StorageCreateTuple"L,
StorageCreateSystemTuple => "StorageCreateSystemTuple"L,
StorageDestroyTuple => "StorageDestroyTuple"L,
StorageReadTupleset => "StorageReadTupleset"L,
StorageReadField => "StorageReadField"L,
StorageWriteField => "StorageWriteField"L,
StorageInitVecPage => "StorageInitVecPage"L,
StorageCheckVecPage => "StorageCheckVecPage"L,
StorageAllocVec => "StorageAllocVec"L,
StorageFreeVec => "StorageFreeVec"L,
StorageModifyVec => "StorageModifyVec"L,
StorageModifyDifficultVec => "StorageModifyDifficultVec"L,
StorageCompactPage => "StorageCompactPage"L,
DBIndexInsert => "DBIndexInsert"L,
DBIndexDelete => "DBIndexDelete"L,
DBIndexOpenScan => "DBIndexOpenScan"L,
DBIndexNextScan => "DBIndexNextScan"L,
DBIndexBiggerKey => "DBIndexBiggerKey"L,
DBIndexEqualKey => "DBIndexEqualKey"L,
BTreeSearchPage => "BTreeSearchPage"L,
BTreeSwapInPage => "BTreeSwapInPage"L,
BTreeSwapOutPage => "BTreeSwapOutPage"L,
CreateEntity => "CreateEntity"L,
CreateRelship => "CreateRelship"L,
ReleaseRelshipSet => "ReleaseRelshipSet"L,
ReleaseEntitySet => "ReleaseEntitySet"L,
SurrogateCreateRelship => "SurrogateCreateRelship"L,
SurrogateDestroyRelship => "SurrogateDestroyRelship"L,
DomainOf => "DomainOf"L,
RelationOf => "RelationOf"L,
SystemGetF => "SystemGetF"L,
DictionaryGetF => "DictionaryGetF"L,
DictionarySetF => "DictionarySetF"L,
GetTupleInfo => "GetTupleInfo"L,
GetTupleInfoMiss => "GetTupleInfoMiss"L,
GetRelationInfo => "GetRelationInfo"L,
GetRelationInfoMiss => "GetRelationInfoMiss"L,
GetAttributeInfo => "GetAttributeInfo"L,
GetAttributeInfoMiss => "GetAttributeInfoMiss"L,
GetDomainInfo => "GetDomainInfo"L,
GetDomainInfoMiss => "GetDomainInfoMiss"L,
SystemGetAttributeInfo => "GetAttributeInfoMiss"L,
ENDCASE => "Don't know"L ];
RETURN[pName];
};
PNameOfTimerEvent: PUBLIC PROC[event: TimerEvent] RETURNS[LONG STRING] = {
pName.length ← 0;
String.AppendString[to: pName, from: SELECT event FROM
-- DBFile--
PilotFileCreateTransaction => "PilotFileCreateTransaction"L,
PilotFileFinishTransaction => "PilotFileFinishTransaction"L,
PilotFileOpen => "PilotFileOpen",
PilotFileReadPage => "PilotFileReadPage"L,
PilotFileWritePage => "PilotFileWritePage"L,
PilotFileGetSize => "PilotFileGetSize"L,
PilotFileSetSize => "PilotFileSetSize"L,
AlpineFileCreateTransaction => "AlpineFileCreateTransaction"L,
AlpineFileFinishTransaction => "AlpineFileFinishTransaction"L,
AlpineFileOpen => "AlpineFileOpen"L,
AlpineFileReadPage => "AlpineFileReadPage"L,
AlpineFileWritePage => "AlpineFileWritePage"L,
AlpineFileGetSize => "AlpineFileGetSize"L,
AlpineFileSetSize =>"AlpineFileSetSize"L,
GetP => "GetP"L,
SetP => "SetP"L,
GetF => "GetF"L,
SetF => "SetF"L,
SurrogateGetF => "SurrogateGetF"L,
SurrogateSetF => "SurrogateSetF"L,
NameOf => "NameOf"L,
ChangeName => "ChangeName"L,
DeclareEntity => "DeclareEntity"L,
DeclareRelship => "DeclareRelship"L,
DestroyEntity => "DestroyEntity"L,
DestroyRelship => "DestroyRelship"L,
RelationSubset => "RelationSubset"L,
DomainSubset => "DomainSubset"L,
NextRelship => "NextRelship"L,
NextEntity => "NextEntity"L,
PrevRelship => "PrevRelship"L,
PrevEntity => "PrevEntity"L,
GetDomainRefAttributes => "GetDomainRefAttributes"L,
OpenToClose => "OpenToClose"L,
ENDCASE => "Don't know"L ];
RETURN[pName];
};
END.--DBStatsImpl
CHANGE LOG
Created by MBrown on February 26, 1981 10:21 AM
-- Pilot version created by editing PerfStatsImpl.
Changed by MBrown on 1-Mar-81 11:47:23
-- Left out a few necessary things, like PNameOfTimerEvent, etc.
Changed by Cattell on 15-Dec-81 10:23:31
-- Converted to IOStream.
Changed by Cattell on April 29, 1982 10:03 pm
-- Added DBView items.
Changed by Willie-Sue on June 24, 1982 12:02 pm
-- IOStream => IO
Changed by Cattell on October 11, 1982 4:22 pm
-- Added some timer events.