lib/stackprof/report.rb in stackprof-0.2.15 vs lib/stackprof/report.rb in stackprof-0.2.16
- old
+ new
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require 'pp'
require 'digest/md5'
module StackProf
class Report
@@ -36,11 +38,11 @@
def overall_samples
@data[:samples]
end
def max_samples
- @data[:max_samples] ||= frames.max_by{ |addr, frame| frame[:samples] }.last[:samples]
+ @data[:max_samples] ||= @data[:frames].values.max_by{ |frame| frame[:samples] }[:samples]
end
def files
@data[:files] ||= @data[:frames].inject(Hash.new) do |hash, (addr, frame)|
if file = frame[:file] and lines = frame[:lines]
@@ -91,21 +93,54 @@
def print_alphabetical_flamegraph(f=STDOUT, skip_common=true)
print_flamegraph(f, skip_common, true)
end
+ StackCursor = Struct.new(:raw, :idx, :length) do
+ def weight
+ @weight ||= raw[1 + idx + length]
+ end
+
+ def [](i)
+ if i >= length
+ nil
+ else
+ raw[1 + idx + i]
+ end
+ end
+
+ def <=>(other)
+ i = 0
+ while i < length && i < other.length
+ if self[i] != other[i]
+ return self[i] <=> other[i]
+ end
+ i += 1
+ end
+
+ return length <=> other.length
+ end
+ end
+
def print_flamegraph(f, skip_common, alphabetical=false)
raise "profile does not include raw samples (add `raw: true` to collecting StackProf.run)" unless raw = data[:raw]
stacks = []
max_x = 0
max_y = 0
- while len = raw.shift
+
+ idx = 0
+ loop do
+ len = raw[idx]
+ break unless len
max_y = len if len > max_y
- stack = raw.slice!(0, len+1)
+
+ stack = StackCursor.new(raw, idx, len)
stacks << stack
- max_x += stack.last
+ max_x += stack.weight
+
+ idx += len + 2
end
stacks.sort! if alphabetical
f.puts 'flamegraph(['
@@ -113,11 +148,11 @@
row_prev = nil
row_width = 0
x = 0
stacks.each do |stack|
- weight = stack.last
+ weight = stack.weight
cell = stack[y] unless y == stack.length-1
if cell.nil?
if row_prev
flamegraph_row(f, x - row_width, y, row_width, row_prev)
@@ -155,11 +190,11 @@
end
f.puts '])'
end
def flamegraph_row(f, x, y, weight, addr)
- frame = frames[addr]
+ frame = @data[:frames][addr]
f.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
@@ -176,11 +211,11 @@
if val == :leaf
child_stacks.each do |stack|
weight += stack.last
end
else
- frame = frames[val]
+ frame = @data[:frames][val]
child_name = "#{ frame[:name] } : #{ frame[:file] }"
child_data = convert_to_d3_flame_graph_format(child_name, child_stacks, depth + 1)
weight += child_data["value"]
children << child_data
end
@@ -652,9 +687,10 @@
else
f.printf " | % 5d | %s", i+1, code
end
end
end
+ rescue SystemCallError
+ f.puts " SOURCE UNAVAILABLE"
end
-
end
end