# TODO: Move class method implementations to Timer::Timer module Timer def self.on!() @on = true end def self.off!() @on = false end def self.on?() @on end def self.off?() !@on end # Output file used by #emit. Default is STDERR (this is set at load-time) def self.file() @file end def self.file=(file) @file = file end # Currently only :s, or :ms. Default is :ms def self.unit() @unit end def self.unit=(unit) @unit = unit end # Number of digits after the decimal point. Default 0 def self.scale() @scale end def self.scale=(scale) @scale = scale end def self.time(label, &block) if on? timer = Timer.new(label) r = yield timer.emit r else yield end end def time(label, &block) ::Timer.time(label, &block) end def self.new(*args) object = Timer.allocate object.send(:initialize, *args) object end class Timer attr_reader :title def file() ::Timer.file end def self.on!() ::Timer.on! end def self.on?() ::Time.on? end def unit() ::Timer.unit end def unit=(unit) ::Timer.unit = unit end def scale() ::Timer.scale end def scale=(scale) ::Timer.scale scale end def initialize(title = nil) @title = title start end def start(title = self.title) @t0 = Time.now; @title = title end def stop() @t1 ||= Time.now end def time() @t1 - @t0 end def to_s(title = self.title) "#{title}: #{Timer.format(time)}" end def emit(title = self.title) stop ::Timer.file.puts to_s(title) if ::Timer.on? end def self.factor() { s: 1, ms: 1000 }[::Timer.unit] end def self.format(time) time ? sprintf("%.#{::Timer.scale}f#{::Timer.unit}", Timer.factor * time) : time.inspect end end private @on = false @file = STDERR @unit = :ms @scale = 0 end #def time(title, &block) # t0 = Time.now # result = yield # t1 = Time.now # dt = (1000 * (t1 - t0)).round(0) # puts "#{title}: #{dt}ms" if defined?(TIME) ? TIME : true # result #end