Skip to content

Instantly share code, notes, and snippets.

@SamSaffron
Last active April 29, 2020 07:10
Show Gist options
  • Select an option

  • Save SamSaffron/88512ff1ede0e438da395800c79cbb08 to your computer and use it in GitHub Desktop.

Select an option

Save SamSaffron/88512ff1ede0e438da395800c79cbb08 to your computer and use it in GitHub Desktop.

Revisions

  1. SamSaffron revised this gist Oct 18, 2017. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions method_profiler.rb
    Original file line number Diff line number Diff line change
    @@ -34,10 +34,12 @@ def self.start

    def self.stop
    finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    data = Thread.current[:_method_profiler]
    start = data.delete(:__start)
    data[:total_duration] = finish - start
    data
    if data = Thread.current[:_method_profiler]
    Thread.current[:_method_profiler] = nil
    start = data.delete(:__start)
    data[:total_duration] = finish - start
    data
    end
    end
    end

  2. SamSaffron created this gist Oct 18, 2017.
    83 changes: 83 additions & 0 deletions method_profiler.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,83 @@
    require 'benchmark/ips'
    require 'redis'
    class MethodProfiler
    def self.patch(klass, methods, name)
    patches = methods.map do |method_name|
    <<~RUBY
    unless defined?(#{method_name}__mp_unpatched)
    alias_method :#{method_name}__mp_unpatched, :#{method_name}
    def #{method_name}(*args, &blk)
    unless prof = Thread.current[:_method_profiler]
    return #{method_name}__mp_unpatched(*args, &blk)
    end
    begin
    start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    #{method_name}__mp_unpatched(*args, &blk)
    ensure
    data = (prof[:#{name}] ||= {duration: 0.0, calls: 0})
    data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
    data[:calls] += 1
    end
    end
    end
    RUBY
    end.join("\n")

    klass.class_eval patches
    end

    def self.start
    Thread.current[:_method_profiler] = {
    __start: Process.clock_gettime(Process::CLOCK_MONOTONIC)
    }
    end

    def self.stop
    finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    data = Thread.current[:_method_profiler]
    start = data.delete(:__start)
    data[:total_duration] = finish - start
    data
    end
    end

    $redis = Redis.new

    class Test
    def work
    #$redis.get 'X'
    end

    def method
    work
    end

    def method_unpatched
    work
    end
    end


    MethodProfiler.patch(Test, [:method], :a_thing)
    MethodProfiler.start

    t = Test.new

    Benchmark.ips do |b|
    b.report "method" do |times|
    i = 0
    while i < times
    t.method
    i += 1
    end
    end

    b.report "method_unpatched" do |times|
    i = 0
    while i < times
    t.method_unpatched
    i += 1
    end
    end

    end