Files
2025-09-29 00:52:08 +02:00

127 lines
3.8 KiB
Ruby
Executable File

#
# File:: RSNProfiler.rb
# Description:: A simpler profiler.
# Author:: Derek Ward <derek.ward@rockstarnorth.com>
# Date:: 14 April 2009
#
#----------------------------------------------------------------------------
# Uses
#----------------------------------------------------------------------------
# None
#----------------------------------------------------------------------------
# Implementation
#----------------------------------------------------------------------------
module Pipeline
module Util
# == Description
# a simple timer/profiler class for profiling performance
# eg.
#
# myTimer = RSNProfiler.new("mytimername")
# func()
# myTimer.end
#
# OR ( with multiple samples counted )
#
# myTimer = RSNProfiler.new("mytimername",false)
# 10.times do
# myTimer.start
# func()
# myTimer.stop
# end
# myTimer.end
class RSNProfiler
@@verbose = true # puts the results?
@@display_detail = true # detailed profile info?
@@display_in_minutes = true # allows you to disable the higher order display units, useful for comparitive display
@@display_in_seconds = true # allows you to disable the higher order display units, useful for comparitive display
@@precision = "%0.4f" # fractional precision formatting string
# == Description
# create the timer, and possibly start it running.
def initialize( name = "RSNProfiler", startup = true )
@name = name
@elapsed = 0.0
@samples = 0
#Kernel.sleep(0.1) # 'supposedly' this might be required to address the update frequency of the Time class , but didn't work?
start() if startup
end
# == Description
# end the timer and optionally display it
def end( display = true )
stop( display )
end
# == Description
# start the timer
def start()
@samples += 1
@start = timestamp()
end
# == Description
# stop/pause the timer and optionally display it
def stop( display = false )
@end = timestamp()
@elapsed += last_duration
throw RuntimeError.new("End and Start times suspect : Start #{@start} End #{@end} Elapsed #{@elapsed}") if @elapsed < 0
puts to_s if ( @@verbose and display )
end
def last_duration
@end-@start
end
def to_s()
@@display_detail ? to_s_detailed : to_s_simple
end
def to_s_detailed()
"#{@name.to_s.ljust(25)} : (samples=#{@samples.to_s.rjust(8)}) : (mean=#{(@@precision % mean_milliseconds()).to_s.rjust(15)}ms) : (elapsed=#{elapsed_string.rjust(20)})"
end
def to_s_simple()
"#{@name.to_s.ljust(25)} : (elapsed=#{elapsed_string.rjust(20)})"
end
def mean_milliseconds()
elapsed_milliseconds/@samples
end
def elapsed_minutes()
@elapsed / 60.0
end
def elapsed_seconds()
@elapsed
end
def elapsed_milliseconds()
@elapsed * 1000.0
end
private
def elapsed_string()
return "#{(@@precision % elapsed_minutes).to_s.rjust(20)} mins" if elapsed_minutes > 1.0 and @@display_in_minutes
return "#{(@@precision % elapsed_seconds).to_s.rjust(20)} secs" if elapsed_seconds > 1.0 and @@display_in_seconds
return "#{(@@precision % elapsed_milliseconds).to_s.rjust(20)} ms"
end
# == Description
# Return the time in micro seconds
def timestamp()
#timestamp = Time.now.floor + (Time.now.usec/1000000.0)
#puts "timestamp : #{timestamp}"
# DW - it looks suspect but sometimes the timestamp look very similar from call to call
# however it seems to have worked in a test I've done.... to be tested a bit better when I get time.
Time.now.to_f
end
end # class RSNProfiler
end # module util
end # module pipeline