module Flows::Plugin::Profiler

Allows to record execution count and time of particular method on class or singleton class.

Recorded data can be displayed in a different ways. See {Profiler::Report} implementations for possible options.

To do a measurement you have call your classes inside {.profile} block.

@note even without calling {.profile} using this module has some performance

impact. Don't left this module used in production environments.

@example

class MyClass
  CallProfiler = Flows::Plugin::Profiler.for_method(:call)
  include CallProfiler

  def call(a, b)
    # some work here
  end
end

class AnotherClass
  CallProfiler = Flows::Plugin::Profiler.for_method(:perform)
  extend CallProfiler

  def self.perform(x)
    MyClass.new.call(x, x)
  end
end

last_result = Flows::Plugin::Profiler.profile do
  AnotherClass.perform(2)
  AnotherClass.perform(6)
end

Profiler.last_report.to_a
# => [
#   [:started,  AnotherClass, :singleton, :perform, nil],
#   [:started,  MyClass,      :instance,  :call,    nil],
#   [:finished, MyClass,      :instance,  :call,    7.3],
#   [:finished, AnotherClass, :singleton, :perform, 10.5],
#   [:started,  AnotherClass, :singleton, :perform, nil],
#   [:started,  MyClass,      :instance,  :call,    nil],
#   [:finished, MyClass,      :instance,  :call,    8.8],
#   [:finished, AnotherClass, :singleton, :perform, 14.2]
# ]

Constants

THREAD_VAR_FLAG
THREAD_VAR_REPORT

Public Class Methods

for_method(method_name) click to toggle source

Generates profiler module for a particular method.

Use `include` for instance methods and `extend` for singleton ones.

@param method_name [Symbol] method to wrap with profiling. @return [Module] module to include or extend.

# File lib/flows/plugin/profiler.rb, line 63
def for_method(method_name)
  Module.new.tap do |mod|
    injector_mod = Injector.make_module(method_name)
    mod.const_set(:Injector, injector_mod)
    mod.extend injector_mod
  end
end
last_report() click to toggle source

@return [Report, nil] last generated report if some.

# File lib/flows/plugin/profiler.rb, line 97
def last_report
  Thread.current[THREAD_VAR_REPORT]
end
profile(report = :raw) { || ... } click to toggle source

Profiles a block execution.

@param report [Report, Symbol]

desired {Report} to be used.
In case of symbol `:some_name` the `Flows::Plugin::Profiler::Report::SomeName.new` will be used.

@yield code to profile @return block result

# File lib/flows/plugin/profiler.rb, line 78
def profile(report = :raw)
  thread = Thread.current

  thread[THREAD_VAR_FLAG] = true
  thread[THREAD_VAR_REPORT] = make_report(report)

  yield
ensure
  thread[THREAD_VAR_FLAG] = false
end
reset() click to toggle source

Resets thread-local variables used for reporting.

# File lib/flows/plugin/profiler.rb, line 90
def reset
  thread = Thread.current
  thread[THREAD_VAR_FLAG] = false
  thread[THREAD_VAR_REPORT] = nil
end

Private Class Methods

make_report(report_or_sym) click to toggle source
# File lib/flows/plugin/profiler.rb, line 103
def make_report(report_or_sym)
  case report_or_sym
  when Report then report_or_sym
  when Symbol
    const_name = report_or_sym.to_s.split('_').map(&:capitalize).join
    Report.const_get(const_name).new
  end
end