514 lines
16 KiB
Plaintext
514 lines
16 KiB
Plaintext
Compile function SRP_Stopwatch(Service, Param1, Param2, Param3)
|
|
|
|
/***********************************************************************************************************************
|
|
|
|
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
|
|
permission from SRP Computer Solutions, Inc.
|
|
|
|
Name : SRP_Stopwatch
|
|
|
|
Description : Service module for benchmarking.
|
|
|
|
Notes : SRP_Stopwatch simplifies benchmarking by tracking multiple benchmarks and displaying them for you at
|
|
the end. You need nothing other than the source code below. There are no dependencies on any other
|
|
DLLs, OCXs, or RDKs. It uses only that which ships with OpenInsight.
|
|
|
|
Parameters :
|
|
Service [in] -- The stopwatch service.
|
|
Param1 [in] -- The service specific parameter.
|
|
Ans [out] -- Response from the service, usually benchmark results.
|
|
|
|
Metadata:
|
|
@@DEFINE_SERVICES_SIGNATURE(@SERVICE, @PARAMS)
|
|
|
|
History : (Date, Initials, Notes)
|
|
01/22/13 krf Original programmer
|
|
05/09/16 krf Updated code to allow Start/Stop to be called multiple times for same name, accumulating a
|
|
total time.
|
|
11/30/16 dmb Fix support for single character stopwatch names in the GetAll and Reset services by
|
|
changing the GE operator to GT.
|
|
11/30/16 dmb If the Name argument is empty, use "<default>". This makes it easier to create a simple
|
|
one-off stopwatch.
|
|
08/17/17 krf Added Count and Average related services
|
|
08/30/17 krf Fixed formatting issues; added secret TEST service
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
If Assigned(Service) else Service = ""
|
|
If Assigned(Param1) else Param1 = ""
|
|
Ans = ""
|
|
|
|
Declare function SRP_Stopwatch, GetTickCount, Max, Index
|
|
Declare subroutine Msg
|
|
|
|
// global common
|
|
Common /SRPStopwatch/ Names@, Total@
|
|
|
|
Convert @Lower.Case to @Upper.Case in Service
|
|
|
|
// benchmark specific commons (Param1 = Name for these services)
|
|
Locate Service in "GETAVERAGE,GETBENCHMARK,GETCOUNT,GETDATA,SHOW,START,STOP,TEST" using "," setting Pos then
|
|
Name = Param1
|
|
If Name EQ '' then
|
|
Name = "<default>"
|
|
end
|
|
If Len(Name) then
|
|
|
|
// Load the commons
|
|
StopWatchName = "SRP_Stopwatch_":Name
|
|
Common //StopWatchName// StartTime@, ElapsedTime@, Count@
|
|
|
|
// Branch to the service
|
|
Begin Case
|
|
Case Service _EQC "GETAVERAGE" ; GoSub GetAverage
|
|
Case Service _EQC "GETBENCHMARK" ; GoSub GetBenchmark
|
|
Case Service _EQC "GETCOUNT" ; GoSub GetCount
|
|
Case Service _EQC "GETDATA" ; GoSub GetData
|
|
Case Service _EQC "SHOW" ; GoSub Show
|
|
Case Service _EQC "START" ; GoSub Start
|
|
Case Service _EQC "STOP" ; GoSub Stop
|
|
Case Service _EQC "TEST" ; GoSub Test
|
|
End Case
|
|
|
|
end
|
|
end else
|
|
|
|
// Non-benchmark specific services
|
|
Begin Case
|
|
Case Service _EQC "GETALL" ; GoSub GetAll
|
|
Case Service _EQC "GETTOTALBENCHMARK" ; GoSub GetTotalBenchmark
|
|
Case Service _EQC "RESET" ; GoSub Reset
|
|
Case Service _EQC "SHOWALL" ; GoSub ShowAll
|
|
End Case
|
|
|
|
end
|
|
|
|
Return Ans
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// SERVICES
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Returns the elapsed time for a benchmark.
|
|
// @@DEFINE_SERVICE(GetAll)
|
|
//-------------------------------------------------------------------------------------------------
|
|
GetAll:
|
|
|
|
// Loop through all the benchmarks and get their results
|
|
LenNames = Len(Names@)
|
|
If LenNames then
|
|
Benchmarks = ""
|
|
Pos = 1
|
|
Loop
|
|
Until Pos GT LenNames
|
|
Name = Names@[Pos, @FM]
|
|
Pos = Col2() + 1
|
|
Benchmarks<-1> = Name:@VM:SRP_Stopwatch("GetData", Name, @VM)
|
|
Repeat
|
|
Ans = Benchmarks
|
|
end
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Returns the average elapsed time for a benchmark.
|
|
// @@DEFINE_SERVICE(GetAverage, Name)
|
|
//-------------------------------------------------------------------------------------------------
|
|
GetAverage:
|
|
|
|
If Len(StartTime@) then
|
|
If Len(ElapsedTime@) then
|
|
Count = If Count@ GT 0 then Count@ else 1
|
|
WorkingTime = Int(ElapsedTime@ / Count)
|
|
GoSub FormatWorkingTime
|
|
end
|
|
end
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Returns the elapsed time for a benchmark.
|
|
// @@DEFINE_SERVICE(GetBenchmark, Name)
|
|
//-------------------------------------------------------------------------------------------------
|
|
GetBenchmark:
|
|
|
|
If Len(StartTime@) then
|
|
If Len(ElapsedTime@) then
|
|
WorkingTime = ElapsedTime@
|
|
GoSub FormatWorkingTime
|
|
end
|
|
end
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Returns the average elapsed time for a benchmark.
|
|
// @@DEFINE_SERVICE(GetAverage, Name)
|
|
//-------------------------------------------------------------------------------------------------
|
|
GetCount:
|
|
|
|
If Len(StartTime@) then
|
|
If Len(ElapsedTime@) then
|
|
Ans = Count@
|
|
end
|
|
end
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Returns the elapsed time for a benchmark.
|
|
// @@DEFINE_SERVICE(GetData, Name, Delim)
|
|
//-------------------------------------------------------------------------------------------------
|
|
GetData:
|
|
|
|
// The delimiter
|
|
Delim = If Assigned(Param2) then Param2 else @FM
|
|
|
|
// Format and return the data
|
|
WorkingTime = ElapsedTime@
|
|
GoSub FormatWorkingTime
|
|
Benchmark = Ans
|
|
Count = If Count@ GT 0 then Count@ else 1
|
|
WorkingTime = Int(ElapsedTime@ / Count)
|
|
GoSub FormatWorkingTime
|
|
Average = Ans
|
|
Ans = Benchmark : Delim : Count : Delim : Average
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Returns the elapsed time for all benchmarks.
|
|
// @@DEFINE_SERVICE(GetTotalBenchmark)
|
|
//-------------------------------------------------------------------------------------------------
|
|
GetTotalBenchmark:
|
|
|
|
If Len(Total@) then
|
|
WorkingTime = Total@
|
|
GoSub FormatWorkingTime
|
|
end
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Resets the stopwatch. This should be called at the beginning of a benchmark.
|
|
// @@DEFINE_SERVICE(Reset)
|
|
//-------------------------------------------------------------------------------------------------
|
|
Reset:
|
|
|
|
// Release all the commons, if any
|
|
LenNames = Len(Names@)
|
|
If LenNames then
|
|
Pos = 1
|
|
Loop
|
|
Until Pos GT LenNames
|
|
Name = Names@[Pos, @FM]
|
|
Pos = Col2() + 1
|
|
StopWatchName = "SRP_Stopwatch_":Name
|
|
FreeCommon StopWatchName
|
|
Repeat
|
|
end
|
|
|
|
// Clear the names
|
|
Names@ = ""
|
|
Total@ = 0
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Shows the benchmark in a message box
|
|
// @@DEFINE_SERVICE(Show, Name)
|
|
//-------------------------------------------------------------------------------------------------
|
|
Show:
|
|
|
|
GoSub GetData
|
|
|
|
Text = ""
|
|
Benchmark = Ans<1>
|
|
Count = Ans<2>
|
|
Average = Ans<3>
|
|
|
|
// Format the benchmark
|
|
If (Index(Benchmark, "00h", 1) EQ 0) else
|
|
Benchmark[1, 4] = ""
|
|
end
|
|
If (Index(Benchmark, "00m", 1) EQ 0) else
|
|
Benchmark[1, 4] = ""
|
|
end
|
|
If (Index(Benchmark, "00s", 1) EQ 0) else
|
|
Benchmark[1, 4] = ""
|
|
end
|
|
Text = Name:" : ":Benchmark
|
|
|
|
// Format the count and average
|
|
If Count GT 1 then
|
|
If (Index(Average, "00h", 1) EQ 0) else
|
|
Average[1, 4] = ""
|
|
end
|
|
If (Index(Average, "00m", 1) EQ 0) else
|
|
Average[1, 4] = ""
|
|
end
|
|
If (Index(Average, "00s", 1) EQ 0) else
|
|
Average[1, 4] = ""
|
|
end
|
|
Text := " : ":Count:" times : ":Average:" avg"
|
|
end
|
|
|
|
// Show it
|
|
MsgStruct = ""
|
|
MsgStruct<1> = Text
|
|
MsgStruct<12> = "SRP Stopwatch Results"
|
|
MsgStruct<18> = "Consolas":@SVM:"-13"
|
|
Msg(@Window, MsgStruct)
|
|
|
|
Ans = 1
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Shows the results for all benchmarks in a message box
|
|
// @@DEFINE_SERVICE(ShowAll)
|
|
//-------------------------------------------------------------------------------------------------
|
|
ShowAll:
|
|
|
|
GoSub GetAll
|
|
|
|
Text = ""
|
|
LenAns = Len(Ans)
|
|
NumBenchmarks = DCount(Ans, @FM)
|
|
If LenAns then
|
|
|
|
// Loop throught the results to determine the best way to format
|
|
MaxNameLen = 5
|
|
MaxCountLen = 1
|
|
HasHours = 0
|
|
HasMinutes = 0
|
|
HasSeconds = 0
|
|
HasCounts = 0
|
|
HasAveHours = 0
|
|
HasAveMinutes = 0
|
|
HasAveSeconds = 0
|
|
Pos = 1
|
|
Loop
|
|
Until Pos GE LenAns
|
|
Result = Ans[Pos, @FM]
|
|
Pos = Col2() + 1
|
|
Name = Result[1, @VM]
|
|
Time = Result[Col2() + 1, @VM]
|
|
Count = Result[Col2() + 1, @VM]
|
|
Average = Result[Col2() + 1, @VM]
|
|
MaxNameLen = Max(MaxNameLen, Len(Name))
|
|
If HasHours else
|
|
HasHours = (Index(Time, "00h", 1) EQ 0)
|
|
end
|
|
If HasMinutes else
|
|
HasMinutes = (Index(Time, "00m", 1) EQ 0)
|
|
end
|
|
If HasSeconds else
|
|
HasSeconds = (Index(Time, "00s", 1) EQ 0)
|
|
end
|
|
//If Count GT 1 OR HasCounts EQ 1 then
|
|
HasCounts = 1
|
|
MaxCountLen = Max(MaxCountLen, Len(Count))
|
|
If HasAveHours else
|
|
HasAveHours = (Index(Average, "00h", 1) EQ 0)
|
|
end
|
|
If HasAveMinutes else
|
|
HasAveMinutes = (Index(Average, "00m", 1) EQ 0)
|
|
end
|
|
If HasAveSeconds else
|
|
HasAveSeconds = (Index(Average, "00s", 1) EQ 0)
|
|
end
|
|
//end
|
|
Repeat
|
|
|
|
// Check how long the total time will be
|
|
If NumBenchmarks GT 1 then
|
|
TotalTime = SRP_Stopwatch("GetTotalBenchmark")
|
|
If HasHours else
|
|
HasHours = (Index(TotalTime, "00h", 1) EQ 0)
|
|
end
|
|
If HasMinutes else
|
|
HasMinutes = (Index(TotalTime, "00m", 1) EQ 0)
|
|
end
|
|
If HasSeconds else
|
|
HasSeconds = (Index(TotalTime, "00s", 1) EQ 0)
|
|
end
|
|
end
|
|
|
|
// Loop through the results to build the message text
|
|
MaxLine = 0
|
|
Pos = 1
|
|
Loop
|
|
Until Pos GE LenAns
|
|
Result = Ans[Pos, @FM]
|
|
Pos = Col2() + 1
|
|
Name = Result[1, @VM]
|
|
Time = Result[Col2() + 1, @VM]
|
|
Count = Result[Col2() + 1, @VM]
|
|
Average = Result[Col2() + 1, @VM]
|
|
If HasHours then
|
|
Swap "00h" with " " in Time
|
|
end else
|
|
Time[1, 4] = ""
|
|
end
|
|
If HasMinutes then
|
|
Swap "00m" with " " in Time
|
|
end else
|
|
Time[1, 4] = ""
|
|
end
|
|
If HasSeconds then
|
|
Swap "00s" with " " in Time
|
|
end else
|
|
Time[1, 4] = ""
|
|
end
|
|
Line = Fmt(Name, "L( )#":(MaxNameLen + 1)):": ":Time
|
|
If HasCounts then
|
|
If HasAveHours then
|
|
Swap "00h" with " " in Average
|
|
end else
|
|
Average[1, 4] = ""
|
|
end
|
|
If HasAveMinutes then
|
|
Swap "00m" with " " in Average
|
|
end else
|
|
Average[1, 4] = ""
|
|
end
|
|
If HasAveSeconds then
|
|
Swap "00s" with " " in Average
|
|
end else
|
|
Average[1, 4] = ""
|
|
end
|
|
Line := " : ":Fmt(Count, "R( )#":MaxCountLen):" times : ":Average:" avg"
|
|
end
|
|
MaxLine = Max(MaxLine, Len(Line))
|
|
Text := Line:"|"
|
|
Repeat
|
|
|
|
If NumBenchmarks GT 1 then
|
|
|
|
// Divider line
|
|
Text := Str("-", MaxLine):"|"
|
|
|
|
// Total line
|
|
If HasHours then
|
|
Swap "00h" with " " in TotalTime
|
|
end else
|
|
TotalTime[1, 4] = ""
|
|
end
|
|
If HasMinutes then
|
|
Swap "00m" with " " in TotalTime
|
|
end else
|
|
TotalTime[1, 4] = ""
|
|
end
|
|
If HasSeconds then
|
|
Swap "00s" with " " in TotalTime
|
|
end else
|
|
TotalTime[1, 4] = ""
|
|
end
|
|
Text := Fmt("Total", "L( )#":(MaxNameLen + 1)):": ":TotalTime
|
|
|
|
end else
|
|
Text[-1, 1] = ""
|
|
end
|
|
|
|
end
|
|
|
|
// Show it
|
|
If Len(Text) then
|
|
MsgStruct = ""
|
|
MsgStruct<1> = Text
|
|
MsgStruct<12> = "SRP Stopwatch Results"
|
|
MsgStruct<18> = "Consolas":@SVM:"-13"
|
|
Msg(@Window, MsgStruct)
|
|
Ans = 1
|
|
end else
|
|
Ans = 0
|
|
end
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Starts a benchmark.
|
|
// @@DEFINE_SERVICE(Start, Name)
|
|
//-------------------------------------------------------------------------------------------------
|
|
Start:
|
|
|
|
// Add the benchmark name if it doesn't exist
|
|
Locate Name in Names@ using @FM setting Pos else
|
|
Names@<-1> = Name
|
|
ElapsedTime@ = 0
|
|
Count@ = 0
|
|
end
|
|
|
|
StartTime@ = GetTickCount()
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Stops a benchmark.
|
|
// @@DEFINE_SERVICE(Stop, Name)
|
|
//-------------------------------------------------------------------------------------------------
|
|
Stop:
|
|
|
|
CurrElapsedTime = GetTickCount() - StartTime@
|
|
ElapsedTime@ += CurrElapsedTime
|
|
Total@ += CurrElapsedTime
|
|
Count@ += 1
|
|
|
|
return
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
// Let's me add test data, so I'm not going to advertise this service. Param2 is the elapsed time,
|
|
// and Param3 is the count for the given name.
|
|
//-------------------------------------------------------------------------------------------------
|
|
Test:
|
|
|
|
// Add the benchmark name if it doesn't exist
|
|
Locate Name in Names@ using @FM setting Pos else
|
|
Names@<-1> = Name
|
|
ElapsedTime@ = Param2
|
|
Count@ = Param3
|
|
Total@ += Param2
|
|
end
|
|
|
|
return
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// INTERNAL GOSUBS
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
FormatWorkingTime:
|
|
|
|
// Hours
|
|
NumHours = Int(WorkingTime / 3600000)
|
|
WorkingTime = Mod(WorkingTime, 3600000)
|
|
|
|
// Minutes
|
|
NumMinutes = Int(WorkingTime / 60000)
|
|
WorkingTime = Mod(WorkingTime, 60000)
|
|
|
|
// Seconds and Millseconds
|
|
NumSeconds = Int(WorkingTime / 1000)
|
|
NumMilliseconds = Mod(WorkingTime, 1000)
|
|
|
|
// Format
|
|
Ans = Fmt(NumHours, "R(0)#2"):"h ":Fmt(NumMinutes, "R(0)#2"):"m ":Fmt(NumSeconds, "R(0)#2"):"s ":Fmt(NumMilliseconds, "R(0)#3"):"ms"
|
|
|
|
return
|
|
|