open-insight/LSL2/STPROC/SRP_STOPWATCH.txt
Infineon\StieberD 7762b129af pre cutover push
2024-09-04 20:33:41 -07:00

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