class Chronometer
Constants
- VERSION
Attributes
trace_events[R]
Public Class Methods
from_file(path, contents: File.read(path))
click to toggle source
# File lib/chronometer.rb, line 11 def self.from_file(path, contents: File.read(path)) new do instance_eval(contents, path) end end
new(&blk)
click to toggle source
# File lib/chronometer.rb, line 17 def initialize(&blk) dsl = DSL.new dsl.instance_exec(&blk) @events = dsl.events @tracepoints = dsl.tracepoints @trace_event_queue = Queue.new @trace_events = [] end
timestamp_us()
click to toggle source
# File lib/chronometer.rb, line 67 def self.timestamp_us Time.now.utc.to_f.*(1_000_000).round end
Public Instance Methods
associate_sub_slices!()
click to toggle source
# File lib/chronometer.rb, line 37 def associate_sub_slices! parents = [] @trace_events.each do |event| case event.event_type when :B parents << event when :E parent = parents.pop event.sub_slices.replace parent.sub_slices if parent parents.last.sub_slices << event unless parents.empty? end end end
drain!()
click to toggle source
# File lib/chronometer.rb, line 31 def drain! loop { @trace_events << @trace_event_queue.pop(true) } rescue ThreadError nil end
install!()
click to toggle source
# File lib/chronometer.rb, line 26 def install! @events.each { |e| install_method_hook(e) } @tracepoints.each { |tp| install_tracepoint(tp) } end
print_trace_event_report(dest, metadata: {})
click to toggle source
# File lib/chronometer.rb, line 51 def print_trace_event_report(dest, metadata: {}) raise ArgumentError, 'cannot manually specify :traceEvents' if metadata.key?(:traceEvents) require 'json' File.open(dest, 'w') do |f| f << JSON.generate(metadata) f.seek(-1, :CUR) # remove closing } f << ',' unless metadata.empty? f << '"traceEvents":[' @trace_events.each_with_index do |te, i| f << ',' unless i == 0 f << JSON.generate(te.to_h) end f << ']}' end end
register_trace_event(event)
click to toggle source
# File lib/chronometer.rb, line 71 def register_trace_event(event) @trace_event_queue << event end
Private Instance Methods
install_method_hook(event)
click to toggle source
# File lib/chronometer.rb, line 77 def install_method_hook(event) cls = event.cls method = event.method unbound_method = cls.instance_method(method) arg_labels = unbound_method.parameters.map(&:last) timer = self cls.send(:define_method, method) do |*args, &blk| context = event.context.call(self) if event.context args_dict = arg_labels.zip(args).to_h args_dict[:context] = context if context start_time = ::Chronometer.timestamp_us event_type = event.event_type if event_type == :X timer.register_trace_event TraceEvent.new( process_id: Process.pid, thread_id: Thread.current.object_id, start_time_usec: ::Chronometer.timestamp_us, event_type: :B, name: event.name ) event_type = :E end r0 = Process.clock_gettime(Process::CLOCK_MONOTONIC) begin unbound_method.bind(self).call(*args, &blk) ensure duration = Process.clock_gettime(Process::CLOCK_MONOTONIC).-(r0).*(1_000_000).round timer.register_trace_event TraceEvent.new( process_id: Process.pid, thread_id: Thread.current.object_id, start_time_usec: event_type == :E ? ::Chronometer.timestamp_us : start_time, event_type: event_type, name: event.name, args: args_dict, category: event.category, duration: duration, cls: cls, method: method ) end end end
install_tracepoint(tracepoint)
click to toggle source
# File lib/chronometer.rb, line 127 def install_tracepoint(tracepoint) event_name, blk = tracepoint TracePoint.trace(event_name) do |tp| next if tp.path == __FILE__ args = { process_id: Process.pid, thread_id: Thread.current.object_id, start_time_usec: ::Chronometer.timestamp_us, event_type: :I, name: event_name } args.update blk.call(tp) if blk te = TraceEvent.new(**args) register_trace_event(te) end end