lib/ruby-prof/printers/flame_graph_printer.rb
# encoding: utf-8 require 'erb' require 'json' module RubyProf # Prints a HTML flame graph visualization of the call tree. # # To use the printer: # # result = RubyProf.profile do # [code to profile] # end # # printer = RubyProf::FlameGraphPrinter.new(result) # printer.print(STDOUT) class FlameGraphPrinter < AbstractPrinter include ERB::Util # Specify print options. # # output - Any IO object, including STDOUT or a file. # # Keyword arguments: # title: - a String to override the default "ruby-prof flame graph" # title of the report. # # Also accepts min_percent:, max_percent:, filter_by:, and sort_method: # from AbstractPrinter. def print(output = STDOUT, title: "ruby-prof flame graph", min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, max_depth: nil, **) @min_percent = min_percent @max_percent = max_percent @filter_by = filter_by @sort_method = sort_method @max_depth = max_depth @title = title output << ERB.new(self.template).result(binding) end attr_reader :title def build_flame_data(call_tree, depth = 0) node = { name: call_tree.target.full_name, value: call_tree.total_time, self_value: call_tree.self_time, called: call_tree.called, children: [] } if @max_depth.nil? || depth < @max_depth call_tree.children.each do |child| node[:children] << build_flame_data(child, depth + 1) end end node end def flame_data_json threads = @result.threads.map do |thread| { id: thread.id, fiber_id: thread.fiber_id, total_time: thread.total_time, data: build_flame_data(thread.call_tree) } end # Disable JSON nesting limit (default 100) so deep call trees serialize. # See https://github.com/ruby-prof/ruby-prof/issues/353 JSON.generate(threads, max_nesting: false) end def template open_asset('flame_graph_printer.html.erb') end end end