Module: WTF::MethodTracker

Defined in:
lib/wtf/method_tracker.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.last_heapObject

Returns the value of attribute last_heap.



38
39
40
# File 'lib/wtf/method_tracker.rb', line 38

def last_heap
  @last_heap
end

.last_timeObject

Returns the value of attribute last_time.



38
39
40
# File 'lib/wtf/method_tracker.rb', line 38

def last_time
  @last_time
end

.stackObject

Returns the value of attribute stack.



38
39
40
# File 'lib/wtf/method_tracker.rb', line 38

def stack
  @stack
end

.statsObject

Returns the value of attribute stats.



38
39
40
# File 'lib/wtf/method_tracker.rb', line 38

def stats
  @stats
end

Class Method Details

.add_stats(at_start = nil) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/wtf/method_tracker.rb', line 63

def add_stats(at_start = nil)
  stat = stats[stack.last]

  this_time = AbsoluteTime.now
  stat[:time] += this_time - last_time
  self.last_time = this_time

  this_heap = GC.stat[:heap_length]
  stat[:heap] += this_heap - last_heap
  self.last_heap = this_heap

  stats[at_start][:freq] += 1 if at_start
end

.dump_statsObject



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/wtf/method_tracker.rb', line 77

def dump_stats
  data = stats.map do |key, val|
    [*key, val[:freq].to_i, val[:time].to_f.round(3), (val[:heap].to_f / 64).round(3)]
  end
  data = data.sort_by {|it| it[3] }.reverse
  data.unshift(%w(class method count time heap_mb))

  time = Time.now.strftime('%m%d_%H%M%S')
  file = File.join(WTF.files_path, "track_#{time}_#{rand(10000)}.csv")
  File.write(file, data.map(&:to_csv).join)
end

.finishObject



57
58
59
60
61
# File 'lib/wtf/method_tracker.rb', line 57

def finish
  add_stats
  dump_stats
  reset_state
end

.on_endObject



52
53
54
55
# File 'lib/wtf/method_tracker.rb', line 52

def on_end
  add_stats
  stack.pop
end

.on_start(*full_name) ⇒ Object



47
48
49
50
# File 'lib/wtf/method_tracker.rb', line 47

def on_start(*full_name)
  add_stats(full_name)
  stack.push(full_name)
end

.override_method(base, name) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/wtf/method_tracker.rb', line 27

def override_method(base, name)
  %{
    def #{name}(*args)
      WTF::MethodTracker.on_start(#{base}, :#{name})
      return_value = super
      WTF::MethodTracker.on_end
      return_value
    end
  }
end

.prepare(base) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/wtf/method_tracker.rb', line 14

def prepare(base)
  methods = base.instance_methods(false) + base.private_instance_methods(false)
  compiled = methods.map do |name|
    override_method(base, name)
  end
  base.module_eval %{
    module Tracking
      #{compiled.join}
    end
    prepend Tracking
  }
end

.reset_stateObject



40
41
42
43
44
45
# File 'lib/wtf/method_tracker.rb', line 40

def reset_state
  self.stats = Hash.new { |h,k| h[k] = { freq: 0, time: 0.0, heap: 0 } }
  self.stack = [[nil, :top]]
  self.last_time = AbsoluteTime.now
  self.last_heap = GC.stat[:heap_length]
end

.start_tracking(*objects) ⇒ Object



4
5
6
7
8
9
10
11
12
# File 'lib/wtf/method_tracker.rb', line 4

def start_tracking(*objects)
  require 'absolute_time'

  objects.each do |object|
    klass = object.is_a?(Module) ? object : object.class
    prepare(klass)
  end
  reset_state
end