1+ # frozen_string_literal: true
2+
13require 'pp'
24require 'digest/md5'
35
@@ -38,7 +40,7 @@ def overall_samples
3840 end
3941
4042 def max_samples
41- @data [ :max_samples ] ||= frames . max_by { |addr , frame | frame [ :samples ] } . last [ :samples ]
43+ @data [ :max_samples ] ||= @data [ : frames] . values . max_by { |frame | frame [ :samples ] } [ :samples ]
4244 end
4345
4446 def files
@@ -93,17 +95,50 @@ def print_alphabetical_flamegraph(f=STDOUT, skip_common=true)
9395 print_flamegraph ( f , skip_common , true )
9496 end
9597
98+ StackCursor = Struct . new ( :raw , :idx , :length ) do
99+ def weight
100+ @weight ||= raw [ 1 + idx + length ]
101+ end
102+
103+ def []( i )
104+ if i >= length
105+ nil
106+ else
107+ raw [ 1 + idx + i ]
108+ end
109+ end
110+
111+ def <=>( other )
112+ i = 0
113+ while i < length && i < other . length
114+ if self [ i ] != other [ i ]
115+ return self [ i ] <=> other [ i ]
116+ end
117+ i += 1
118+ end
119+
120+ return length <=> other . length
121+ end
122+ end
123+
96124 def print_flamegraph ( f , skip_common , alphabetical = false )
97125 raise "profile does not include raw samples (add `raw: true` to collecting StackProf.run)" unless raw = data [ :raw ]
98126
99127 stacks = [ ]
100128 max_x = 0
101129 max_y = 0
102- while len = raw . shift
130+
131+ idx = 0
132+ loop do
133+ len = raw [ idx ]
134+ break unless len
103135 max_y = len if len > max_y
104- stack = raw . slice! ( 0 , len +1 )
136+
137+ stack = StackCursor . new ( raw , idx , len )
105138 stacks << stack
106- max_x += stack . last
139+ max_x += stack . weight
140+
141+ idx += len + 2
107142 end
108143
109144 stacks . sort! if alphabetical
@@ -115,7 +150,7 @@ def print_flamegraph(f, skip_common, alphabetical=false)
115150 x = 0
116151
117152 stacks . each do |stack |
118- weight = stack . last
153+ weight = stack . weight
119154 cell = stack [ y ] unless y == stack . length -1
120155
121156 if cell . nil?
@@ -157,7 +192,7 @@ def print_flamegraph(f, skip_common, alphabetical=false)
157192 end
158193
159194 def flamegraph_row ( f , x , y , weight , addr )
160- frame = frames [ addr ]
195+ frame = @data [ : frames] [ addr ]
161196 f . print ',' if @rows_started
162197 @rows_started = true
163198 f . puts %{{"x":#{ x } ,"y":#{ y } ,"width":#{ weight } ,"frame_id":#{ addr } ,"frame":#{ frame [ :name ] . dump } ,"file":#{ frame [ :file ] . dump } }}
@@ -178,7 +213,7 @@ def convert_to_d3_flame_graph_format(name, stacks, depth)
178213 weight += stack . last
179214 end
180215 else
181- frame = frames [ val ]
216+ frame = @data [ : frames] [ addr ]
182217 child_name = "#{ frame [ :name ] } : #{ frame [ :file ] } "
183218 child_data = convert_to_d3_flame_graph_format ( child_name , child_stacks , depth + 1 )
184219 weight += child_data [ "value" ]
0 commit comments