lib/stackprof/report.rb in stackprof-0.2.3 vs lib/stackprof/report.rb in stackprof-0.2.4

- old
+ new

@@ -77,9 +77,74 @@ print frames.map{ |a| data[:frames][a][:name] }.join(';') puts " #{weight}" end end + def print_flamegraph(f=STDOUT, skip_common=true) + raise "profile does not include raw samples" unless raw = data[:raw] + + stacks = [] + max_y = 0 + while len = raw.shift + max_y = len if len > max_y + stacks << raw.slice!(0, len+1) + end + max_x = stacks.inject(0){ |sum, (*stack, weight)| sum + weight } + + f.puts 'flamegraph([' + max_y.times do |y| + row_prev = nil + row_width = 0 + x = 0 + + stacks.each do |*stack, weight| + cell = stack[y] + + if cell.nil? + if row_prev + flamegraph_row(x - row_width, y, row_width, row_prev) + end + + row_prev = nil + x += weight + next + end + + if row_prev.nil? # start new row with this cell + row_width = weight + row_prev = cell + x += weight + + elsif row_prev == cell # grow current row along x-axis + row_width += weight + x += weight + + else # end current row and start new row + flamegraph_row(x - row_width, y, row_width, row_prev) + x += weight + row_prev = cell + row_width = weight + end + + row_prev = cell + end + + if row_prev + next if skip_common && row_width == max_x + + flamegraph_row(x - row_width, y, row_width, row_prev) + end + end + f.puts '])' + end + + def flamegraph_row(x, y, weight, addr) + frame = frames[addr] + print ',' if @rows_started + @rows_started = true + f.puts %{{"x":#{x},"y":#{y},"width":#{weight},"frame_id":#{addr},"frame":#{frame[:name].dump},"file":#{frame[:file].dump}}} + end + def print_graphviz(filter = nil, f = STDOUT) if filter mark_stack = [] list = frames list.each{ |addr, frame| mark_stack << addr if frame[:name] =~ filter }