lib/ztk/benchmark.rb
require 'benchmark'
module ZTK
# Benchmark Error Class
#
# @author Zachary Patten <zpatten AT jovelabs DOT io>
class BenchmarkError < Error; end
# Benchmark Class
#
# This class contains a benchmarking tool which doubles to supply indications
# of activity to the console user during long running tasks.
#
# It can be run strictly for benchmarking (the default) or if supplied with
# the appropriate options it will display output to the user while
# benchmarking the supplied block.
#
# @example Benchmark a simple sleep statement
#
# message = "I wonder how long this will take?"
# mark = " ...looks like it took %0.4f seconds!"
# ZTK::Benchmark.bench(:message => message, :mark => mark) do
# sleep(1.5)
# end
#
# @author Zachary Patten <zpatten AT jovelabs DOT io>
class Benchmark
class << self
# Benchmark the supplied block.
#
# If *message* and *mark* options are used, then the *message* text will
# be displayed to the user. The the supplied *block* is yielded inside
# a *ZTK::Spinner.spin* call. This will provide the spinning cursor while
# the block executes. It is advisable to not have output sent to the
# console during this period.
#
# Once the block finishes executing, the *mark* text is displayed with
# the benchmark supplied to it as a sprintf option. One could use "%0.4f"
# in a *String* for example to get the benchmark time embedded in it
#
# @see Kernel#sprintf
#
# @param [Hash] options Configuration options hash.
# @option options [String] :message The *String* to be displayed to the
# user before the block is yielded.
# @option options [String] :mark The *String* to be displayed to the user
# after the block is yielded. This *String* should have an *sprintf*
# floating point macro in it if the benchmark is desired to be embedded
# in the given *String*.
# @option options [Boolean] :use_spinner (true) Whether or not to use the
# ZTK::Spinner while benchmarking.
#
# @yield Block should execute the tasks to be benchmarked.
# @yieldreturn [Object] The return value of the block is ignored.
# @return [Float] The benchmark time.
#
def bench(options={}, &block)
options = Base.build_config({
:use_spinner => true
}, options)
!block_given? and Base.log_and_raise(options.ui.logger, BenchmarkError, "You must supply a block!")
if (!options.message.nil? && !options.message.empty?)
options.ui.stdout.print(options.message)
options.ui.logger.info { options.message.strip }
end
benchmark = ::Benchmark.realtime do
if options.use_spinner
ZTK::Spinner.spin(options) do
yield
end
else
yield
end
end
if (!options.mark.nil? && !options.mark.empty?)
options.ui.stdout.print(options.mark % benchmark)
options.ui.logger.info { options.mark.strip % benchmark }
end
benchmark
end
end
end
end