def bench(label = nil) Rack::Bench.close_bench_item(Kernel.caller[0]) Rack::Bench.on if label Rack::Bench.push_bench_item( :label => label, :start_time => Time.now, :start_context => Kernel.caller[0] ) end end module Rack # Rack::Bench adds benchmarking capabilities to Kiss applications. # # bench(label) starts a new timer, which ends upon the next call to # bench, or when execution returns to Rack::Bench. # # bench can be called without a label to end the previous timer # without starting a new one. # # Total request duration is also displayed for any request in which # the bench function is called. class Bench def self.on @@bench = true end def self.close_bench_item(end_context = nil) if @@bench_items[-1] && !@@bench_items[-1][:end_time] @@bench_items[-1][:end_time] = Time.now @@bench_items[-1][:end_context] = end_context end end def self.push_bench_item(item) @@bench_items.push(item) end def initialize(app) @app = app end def call(env) @@bench = false @@bench_items = [] start_time = Time.now code, headers, body = @app.call(env) end_time = Time.now if @@bench Rack::Bench.close_bench_item contents = <<-EOT EOT contents += @@bench_items.map do |item| start_link = context_link(item[:start_context]) end_link = context_link(item[:end_context]) <<-EOT
#{item[:label].gsub(/\ kiss bench
started at #{start_link}
ended at #{end_link || 'return to kiss bench'}
EOT end.join contents += <<-EOT
TOTAL request duration: #{sprintf("%0.3f",end_time.to_f - start_time.to_f)} s
kiss bench request total
EOT else contents = '' end body.each {|p| contents += p } headers['Content-Length'] = contents.length.to_s [ code, headers, contents ] end def absolute_path(filename) filename = ( filename =~ /\A\// ? '' : (Dir.pwd + '/') ) + filename end def context_link(context) return nil unless context filename, line, method = context.split(/:/) textmate_url = "txmt://open?url=file://" + h(absolute_path(filename)) + '&line=' + line %Q(#{filename}:#{line} #{method}) end def textmate_href(frame) "txmt://open?url=file://" + h(absolute_path(context)).sub(/:/,'&line=') end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj).gsub(/^(\s+)/) {' ' * $1.length} else Utils.escape_html(obj.inspect) end end end end