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