Class: SamplingProf

Inherits:
Object
  • Object
show all
Defined in:
lib/sampling_prof.rb,
lib/sampling_prof/internal.rb

Defined Under Namespace

Classes: Sampling, Threads

Constant Summary collapse

DEFAULT_OUTPUT_FILE =
'profile.txt'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, &output_handler) ⇒ SamplingProf

options:

sampling_interval: default to 0.1 second
multithreading: default to false
output_interval: default to (multithreading ? 60 : nil)
&output_handler: default to write into output_file


17
18
19
20
21
22
23
24
25
26
27
# File 'lib/sampling_prof.rb', line 17

def initialize(*args, &output_handler)
  self.sampling_interval = args[0] || 0.1
  self.multithreading = args[1] || false
  if args.length > 2
    self.output_interval = args[2]
  else
    self.output_interval = multithreading ? 60 : nil
  end
  self.output_handler = block_given? ? output_handler : default_output_handler
  internal_initialize if respond_to?(:internal_initialize)
end

Instance Attribute Details

#multithreadingObject

Returns the value of attribute multithreading.



105
106
107
# File 'lib/sampling_prof/internal.rb', line 105

def multithreading
  @multithreading
end

#output_fileObject



29
30
31
# File 'lib/sampling_prof.rb', line 29

def output_file
  @output_file ||= DEFAULT_OUTPUT_FILE
end

#output_handlerObject

Returns the value of attribute output_handler.



105
106
107
# File 'lib/sampling_prof/internal.rb', line 105

def output_handler
  @output_handler
end

#output_intervalObject

Returns the value of attribute output_interval.



105
106
107
# File 'lib/sampling_prof/internal.rb', line 105

def output_interval
  @output_interval
end

#sampling_intervalObject

Returns the value of attribute sampling_interval.



105
106
107
# File 'lib/sampling_prof/internal.rb', line 105

def sampling_interval
  @sampling_interval
end

Instance Method Details

#default_output_handlerObject



40
41
42
43
44
45
46
# File 'lib/sampling_prof.rb', line 40

def default_output_handler
  lambda do |data|
    File.open(output_file, 'w') do |f|
      f.write(data)
    end
  end
end

#flat_report(nodes, counts) ⇒ Object



69
70
71
72
73
74
75
76
77
# File 'lib/sampling_prof.rb', line 69

def flat_report(nodes, counts)
  total = counts.map{|_,sc,tc| sc}.reduce(:+)
  reports = counts.reject{|_,sc,tc| sc == 0}.sort_by{|_,sc,tc| -sc}.map do |id, sc, tc|
    [sc, '%.2f%' % (100 * sc.to_f/total),
     tc, '%.2f%' % (100 * tc.to_f/total),
     nodes[id]]
  end
  [total, reports]
end

#internal_initializeObject



107
108
109
110
111
# File 'lib/sampling_prof/internal.rb', line 107

def internal_initialize
  @running = false
  @sampling_thread = nil
  @threads = Threads.new
end

#profile(&block) ⇒ Object



33
34
35
36
37
38
# File 'lib/sampling_prof.rb', line 33

def profile(&block)
  start
  yield if block_given?
ensure
  stop if block_given?
end

#profiling?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/sampling_prof/internal.rb', line 156

def profiling?
  !!@sampling_thread
end

#report(type, output = $stdout) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/sampling_prof.rb', line 48

def report(type, output=$stdout)
  runtime, nodes, counts, call_graph = File.read(output_file).split("\n\n")
  nodes = nodes.split("\n").inject({}) do |ret, l|
    n, i = l.split(',')
    ret[i.to_i] = n
    ret
  end

  counts = counts.split("\n").map do |l|
    l.split(',').map(&:to_i)
  end
  total_samples, report = flat_report(nodes, counts)

  output.puts "runtime: #{runtime.to_f/1000} secs"
  output.puts "total samples: #{total_samples}"
  output.puts "self\t%\ttotal\t%\tname"
  report.first(20).each do |v|
    output.puts v.join("\t")
  end
end

#startObject



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/sampling_prof/internal.rb', line 113

def start
  if @multithreading || !@running
    @running = true
    @threads.add(Thread.current)
    @sampling_thread ||= Thread.start do
      loop do
        sampling = Sampling.new(@threads)
        loop do
          break unless @running
          if @multithreading
            break if output_interval < sampling.runtime
          end
          sampling.process
          sleep @sampling_interval
        end
        if sampling.sampling_data?
          @output_handler.call(sampling.result)
        end
        break unless @running
      end
    end
    true
  end
end

#stopObject



138
139
140
141
142
143
144
145
146
147
# File 'lib/sampling_prof/internal.rb', line 138

def stop
  if @running
    if @multithreading
      @threads.delete(Thread.current)
    else
      terminate
    end
    true
  end
end

#terminateObject



149
150
151
152
153
154
# File 'lib/sampling_prof/internal.rb', line 149

def terminate
  @running = false
  @sampling_thread.join
  @sampling_thread = nil
  true
end