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 }