1-
2-
3- let queue = [ ]
4-
5- function queuehandler ( ms ) {
6-
7- // Calculate the time difference in milliseconds
8- queue . forEach ( element => {
9- const date1 = new Date ( ) ;
10- element ( ) ;
11- while ( new date ( ) - date1 < ms )
12- console . log ( "slept a tick" )
13- } ) ;
14-
15-
16- }
17-
18-
191// GLOBAL STATE
202let calls = { } ;
213let deadBeat = { } ;
224let idMap = { } ;
235let aggregates = { } ;
246let processedBatches = 0 ;
257const renderEvery = 5 ;
8+ let currentRoot = null ;
269
2710
2811
@@ -33,16 +16,19 @@ function finalizeProcessing() {
3316 renderForest ( forest ) ;
3417 renderTimeline ( Object . values ( calls ) ) ;
3518 renderSummary ( aggregates ) ;
19+ addToFlamegraph ( forest ) ;
3620 renderFlamegraph ( flamegraphRoot ) ;
3721 if ( forest ) showFunctionDetails ( forest [ 0 ] ) ;
3822}
3923
4024function maybeRender ( ) {
4125 if ( processedBatches % renderEvery === 0 ) {
4226 requestSummaryRender ( ) ;
43- requestTreeRender ( ) ;
27+ renderForestSnapshot = buildForest ( calls ) ;
28+ requestTreeRender ( renderForestSnapshot ) ;
29+
30+ if ( flamegraphActive ) { addToFlamegraph ( renderForestSnapshot ) ; requestFlamegraphRender ( ) ; }
4431 // renderTimeline(Object.values(calls));
45- // if (flamegraphActive) requestFlamegraphRender();
4632 }
4733}
4834
@@ -66,8 +52,6 @@ function processBatch(batch) {
6652
6753 cCall = calls [ id ] ;
6854
69- addToFlamegraph ( cCall ) ;
70-
7155
7256
7357 // update aggregates
@@ -184,7 +168,7 @@ function renderSummary(aggregates) {
184168
185169// Flame graph handler ===============================================================================================================================================================================================================
186170let flamegraphLastRender = 0 ;
187- const flamegraphRenderInterval = 100 ;
171+ const flamegraphRenderInterval = 1000 ;
188172
189173let resizeObserver ;
190174
@@ -199,7 +183,6 @@ const color = d3.scaleOrdinal(d3.schemeTableau10);
199183function getNodePath ( d ) {
200184 return d . ancestors ( ) . map ( n => n . data . name ) . reverse ( ) . join ( "/" ) ;
201185}
202-
203186function renderFlamegraph ( data ) {
204187 const container = document . getElementById ( "flamegraphView" ) ;
205188 const width = container . clientWidth ;
@@ -210,21 +193,24 @@ function renderFlamegraph(data) {
210193 const root = d3 . hierarchy ( data ) . sum ( d => d . value ) ;
211194 partition ( root ) ;
212195
213- // Initialize SVG & zoom once
196+ // Save for semantic zoom
197+ currentRoot = data ;
198+
199+ const MIN_WIDTH = 0 ;
200+ const nodes = root . descendants ( ) . filter ( d => ( d . x1 - d . x0 ) > MIN_WIDTH ) ;
201+
214202 if ( ! flamegraphSVG ) {
215203 flamegraphSVG = d3 . select ( "#flamegraphView" ) . append ( "svg" )
216- . attr ( "width" , width )
217- . attr ( "height" , height ) ;
204+ . attr ( "width" , width ) . attr ( "height" , height ) ;
218205
219206 flamegraphG = flamegraphSVG . append ( "g" ) ;
220207
221208 const zoom = d3 . zoom ( ) . scaleExtent ( [ 0.5 , 10 ] )
222209 . on ( "zoom" , ( event ) => flamegraphG . attr ( "transform" , event . transform ) ) ;
223210 flamegraphSVG . call ( zoom ) ;
224211
225- // Add reset zoom button
226212 const button = document . createElement ( "button" ) ;
227- button . innerText = "Reset Zoom" ;
213+ button . innerText = "Zoom Out " ;
228214 button . style . position = "absolute" ;
229215 button . style . top = "10px" ;
230216 button . style . right = "20px" ;
@@ -237,24 +223,26 @@ function renderFlamegraph(data) {
237223 button . style . cursor = "pointer" ;
238224 document . body . appendChild ( button ) ;
239225 button . onclick = ( ) => {
240- flamegraphSVG . transition ( ) . duration ( 500 ) . call ( zoom . transform , d3 . zoomIdentity ) ;
226+ renderFlamegraph ( flamegraphRoot ) ;
241227 } ;
242228 } else {
243229 flamegraphSVG . attr ( "width" , width ) . attr ( "height" , height ) ;
244230 }
245231
246- const rects = flamegraphG . selectAll ( "g.node" )
247- . data ( root . descendants ( ) , getNodePath ) ;
248-
232+ const rects = flamegraphG . selectAll ( "g.node" ) . data ( nodes , getNodePath ) ;
249233 rects . exit ( ) . remove ( ) ;
250234
251235 const enter = rects . enter ( ) . append ( "g" ) . attr ( "class" , "node" ) ;
236+ enter . append ( "rect" ) ;
237+ enter . append ( "title" ) ;
252238
253- enter . append ( "rect" )
239+ const merged = enter . merge ( rects ) ;
240+
241+ merged . select ( "rect" )
254242 . attr ( "x" , d => d . x0 ) . attr ( "y" , d => d . y0 )
255243 . attr ( "width" , d => d . x1 - d . x0 ) . attr ( "height" , d => d . y1 - d . y0 )
256244 . attr ( "fill" , d => color ( d . data . name ) )
257- . on ( "click" , ( event , d ) => zoomIntoNode ( d , partition , root ) )
245+ . on ( "click" , ( event , d ) => zoomIntoNode ( d ) )
258246 . on ( "mouseover" , function ( event , d ) {
259247 d3 . select ( this ) . attr ( "stroke" , "#fff" ) . attr ( "stroke-width" , 2 ) ;
260248 showTooltip ( event , d ) ;
@@ -264,17 +252,7 @@ function renderFlamegraph(data) {
264252 hideTooltip ( ) ;
265253 } ) ;
266254
267- enter . append ( "title" )
268- . text ( d => `${ d . data . name } : ${ Math . round ( d . value ) } ms` ) ;
269-
270- const merged = enter . merge ( rects ) ;
271- merged . select ( "rect" ) . transition ( ) . duration ( 200 )
272- . attr ( "x" , d => d . x0 ) . attr ( "y" , d => d . y0 )
273- . attr ( "width" , d => d . x1 - d . x0 ) . attr ( "height" , d => d . y1 - d . y0 )
274- . attr ( "fill" , d => color ( d . data . name ) ) ;
275-
276- merged . select ( "title" )
277- . text ( d => `${ d . data . name } : ${ Math . round ( d . value ) } ms` ) ;
255+ merged . select ( "title" ) . text ( d => `${ d . data . name } : ${ Math . round ( d . value ) } ms` ) ;
278256}
279257
280258function zoomIntoNode ( target , partition , root ) {
@@ -313,37 +291,44 @@ function hideTooltip() {
313291}
314292
315293function addToFlamegraph ( call ) {
316- let current = call ;
317- const path = [ ] ;
318- while ( current ) {
319- path . unshift ( current . function ) ;
320- current = current . parent_call_id ? calls [ current . parent_call_id ] : null ;
321- }
322-
323- let node = flamegraphRoot ;
324- for ( const func of path ) {
325- let child = node . children . find ( c => c . name === func ) ;
326- if ( ! child ) {
327- child = { name : func , value : 0 , children : [ ] } ;
328- node . children . push ( child ) ;
329- }
330- node = child ;
331- }
332- node . value += call . end - call . start ;
294+ flamegraphRoot = { name : "__ROOT__" , value : 0 , children : [ ] } ;
295+ call . forEach ( element => {
296+ flamegraphRoot . children . push ( get_path_from_root ( element ) ) ;
297+ } ) ;
333298}
334299
335300
301+ function get_path_from_root ( call ) {
302+
303+ const node = {
304+ name : call . function ,
305+ value : call . duration ,
306+ children : [ ]
307+ } ;
308+
309+ // Recurse over children, if any
310+ if ( call . children && call . children . size > 0 ) {
311+ for ( const childCall of call . children ) {
312+ node . children . push ( get_path_from_root ( calls [ childCall ] ) ) ;
313+ }
314+ }
315+ return node ;
316+
336317
337- function requestFlamegraphRender ( ) {
338- if ( flamegraphRenderTimeout ) {
339- clearTimeout ( flamegraphRenderTimeout ) ;
340- }
341- flamegraphRenderTimeout = setTimeout ( ( ) => {
342- renderFlamegraph ( flamegraphRoot ) ;
343- } , 100 ) ; // slight delay to batch fast incoming updates
344318}
345319
320+ function requestFlamegraphRender ( ) {
346321
322+ const now = performance . now ( ) ;
323+ if ( now - flamegraphLastRender >= flamegraphRenderInterval ) {
324+ summaryLastRender = now ;
325+ currentRoot = flamegraphRoot ;
326+ renderFlamegraph ( flamegraphRoot ) ;
327+ }
328+ }
329+ function zoomIntoNode ( d ) {
330+ renderFlamegraph ( d . data ) ; // drill into this node
331+ }
347332// tree Handler ===============================================================================================================================================================================================================
348333let treeLastRender = 0 ;
349334const treeRenderInterval = 100 ;
@@ -352,11 +337,10 @@ let rowPool = [];
352337
353338
354339
355- function requestTreeRender ( ) {
340+ function requestTreeRender ( renderForestSnapshot ) {
356341 const now = performance . now ( ) ;
357342 if ( now - treeLastRender >= treeRenderInterval ) {
358343 treeLastRender = now ;
359- renderForestSnapshot = buildForest ( calls ) ;
360344 renderVirtualTree ( renderForestSnapshot ) ;
361345 }
362346}
0 commit comments