# # File:: RSNProfiler.rb # Description:: A simpler profiler. # Author:: Derek Ward # 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