Last Updated: February 25, 2016
·
288
· gobert

Measure and Benchmark Easily I/O in ruby

1. Create the mixin Benchmarkable

module Benchmarkable
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def benchmark!(etalon, &block)
      @t_start = Time.now
      @res    = begin
        yield
      rescue => e
        raise e
      ensure
        @t_end   = Time.now
        `echo #{@t_end - @t_start} >> tmp/#{etalon}`
      end
      @res
    end

    def time_of(etalon)
      File.read("./tmp/#{etalon}").split("\n").map(&:to_f)
    end
  end
end

2. Use it!

Having our code like:

class ApiOrCache
  def self.get_track(musician_name)
      get_track_by_db(musician_name) || get_track_by_api(musician_name)
    end
  end
end

we will transform it to use the mixin Benchmarkable

class ApiOrCache
  include Benchmarkable
  def self.get_track(musician_name)
    benchmark!(:db) do
      get_track_by_db(musician_name)
    end || benchmark!(:api) do
     get_track_by_api(musician_name)
    end
  end
end

3. Analyzing the results

ApiOrCache.time_of(:api)
=> [0.31668, 0.108643, 0.200778, 0.159974, 0.134641, 8.83668]

Reopening the class Enumerable with some math stuff you can enjoy:

ApiOrCache.time_of(:api).sum  # cumulative time passed in the API
=> 9.757396
ApiOrCache.time_of(:api).mean # average time passed per API call
=> 1.6262326666666667
ApiOrCache.time_of(:api).standard_deviation # standard deviation of the time passed per API call around (in average, how far is it from 1.6 s)
=> 3.533135675693401
ApiOrCache.time_of(:db).mean # average time passed in the cache
=> 0.3236666666666667