@@ -6,6 +6,7 @@ let normalData = null;
66let invertedData = null ;
77let currentThreadFilter = 'all' ;
88let isInverted = false ;
9+ let useModuleNames = true ;
910
1011// Heat colors are now defined in CSS variables (--heat-1 through --heat-8)
1112// and automatically switch with theme changes - no JS color arrays needed!
@@ -67,6 +68,9 @@ function resolveStringIndices(node, table) {
6768 if ( typeof resolved . module_name === 'number' ) {
6869 resolved . module_name = resolveString ( resolved . module_name ) ;
6970 }
71+ if ( typeof resolved . name_module === 'number' ) {
72+ resolved . name_module = resolveString ( resolved . name_module ) ;
73+ }
7074
7175 if ( Array . isArray ( resolved . source ) ) {
7276 resolved . source = resolved . source . map ( index =>
@@ -86,6 +90,14 @@ function escapeHtml(str) {
8690 return str . replace ( / & / g, "&" ) . replace ( / < / g, "<" ) . replace ( / > / g, ">" ) ;
8791}
8892
93+ // Get display path based on user preference (module name or basename)
94+ function getDisplayName ( moduleName , filename ) {
95+ if ( useModuleNames ) {
96+ return moduleName || filename ;
97+ }
98+ return filename ? filename . split ( '/' ) . pop ( ) : filename ;
99+ }
100+
89101function selectFlamegraphData ( ) {
90102 const baseData = isShowingElided ? elidedFlamegraphData : normalData ;
91103
@@ -258,7 +270,8 @@ function updateStatusBar(nodeData, rootValue) {
258270
259271 const fileEl = document . getElementById ( 'status-file' ) ;
260272 if ( fileEl && filename && filename !== "~" ) {
261- fileEl . textContent = lineno ? `${ moduleName } :${ lineno } ` : moduleName ;
273+ const displayName = getDisplayName ( moduleName , filename ) ;
274+ fileEl . textContent = lineno ? `${ displayName } :${ lineno } ` : displayName ;
262275 }
263276
264277 const funcEl = document . getElementById ( 'status-func' ) ;
@@ -307,7 +320,8 @@ function createPythonTooltip(data) {
307320
308321 const funcname = resolveString ( d . data . funcname ) || resolveString ( d . data . name ) ;
309322 const filename = resolveString ( d . data . filename ) || "" ;
310- const moduleName = escapeHtml ( resolveString ( d . data . module_name ) || "" ) ;
323+ const moduleName = resolveString ( d . data . module_name ) || "" ;
324+ const displayName = escapeHtml ( useModuleNames ? ( moduleName || filename ) : filename ) ;
311325 const isSpecialFrame = filename === "~" ;
312326
313327 // Build source section
@@ -376,7 +390,7 @@ function createPythonTooltip(data) {
376390 }
377391
378392 const fileLocationHTML = isSpecialFrame ? "" : `
379- <div class="tooltip-location">${ moduleName } ${ d . data . lineno ? ":" + d . data . lineno : "" } </div>` ;
393+ <div class="tooltip-location">${ displayName } ${ d . data . lineno ? ":" + d . data . lineno : "" } </div>` ;
380394
381395 // Differential stats section
382396 let diffSection = "" ;
@@ -588,6 +602,7 @@ function createFlamegraph(tooltip, rootValue, data) {
588602 . minFrameSize ( 1 )
589603 . tooltip ( tooltip )
590604 . inverted ( true )
605+ . getName ( d => resolveString ( useModuleNames ? d . data . name_module : d . data . name ) || resolveString ( d . data . name ) || '' )
591606 . setColorMapper ( function ( d ) {
592607 if ( d . depth === 0 ) return 'transparent' ;
593608
@@ -631,24 +646,24 @@ function updateSearchHighlight(searchTerm, searchInput) {
631646 const funcname = resolveString ( d . data . funcname ) || "" ;
632647 const filename = resolveString ( d . data . filename ) || "" ;
633648 const moduleName = resolveString ( d . data . module_name ) || "" ;
649+ const displayName = getDisplayName ( moduleName , filename ) ;
634650 const lineno = d . data . lineno ;
635651 const term = searchTerm . toLowerCase ( ) ;
636652
637- // Check if search term looks like module :line pattern
653+ // Check if search term looks like path :line pattern
638654 const fileLineMatch = term . match ( / ^ ( .+ ) : ( \d + ) $ / ) ;
639655 let matches = false ;
640656
641657 if ( fileLineMatch ) {
642658 const searchFile = fileLineMatch [ 1 ] ;
643659 const searchLine = parseInt ( fileLineMatch [ 2 ] , 10 ) ;
644- matches = moduleName . toLowerCase ( ) . includes ( searchFile ) && lineno === searchLine ;
660+ matches = displayName . toLowerCase ( ) . includes ( searchFile ) && lineno === searchLine ;
645661 } else {
646662 // Regular substring search
647663 matches =
648664 name . toLowerCase ( ) . includes ( term ) ||
649665 funcname . toLowerCase ( ) . includes ( term ) ||
650- moduleName . toLowerCase ( ) . includes ( term ) ||
651- filename . toLowerCase ( ) . includes ( term ) ;
666+ displayName . toLowerCase ( ) . includes ( term ) ;
652667 }
653668
654669 if ( matches ) {
@@ -1134,7 +1149,8 @@ function populateStats(data) {
11341149 if ( isSpecialFrame ) {
11351150 fileEl . textContent = '--' ;
11361151 } else {
1137- fileEl . textContent = `${ moduleName } :${ lineno } ` ;
1152+ const displayName = getDisplayName ( moduleName , filename ) ;
1153+ fileEl . textContent = `${ displayName } :${ lineno } ` ;
11381154 }
11391155 }
11401156 if ( percentEl ) percentEl . textContent = `${ h . directPercent . toFixed ( 1 ) } %` ;
@@ -1151,8 +1167,10 @@ function populateStats(data) {
11511167 if ( i < hotSpots . length && hotSpots [ i ] ) {
11521168 const h = hotSpots [ i ] ;
11531169 const moduleName = h . module_name || 'unknown' ;
1154- const hasValidLocation = moduleName !== 'unknown' && h . lineno !== '?' ;
1155- const searchTerm = hasValidLocation ? `${ moduleName } :${ h . lineno } ` : h . funcname ;
1170+ const filename = h . filename || 'unknown' ;
1171+ const displayName = getDisplayName ( moduleName , filename ) ;
1172+ const hasValidLocation = displayName !== 'unknown' && h . lineno !== '?' ;
1173+ const searchTerm = hasValidLocation ? `${ displayName } :${ h . lineno } ` : h . funcname ;
11561174 card . dataset . searchterm = searchTerm ;
11571175 card . onclick = ( ) => searchForHotspot ( searchTerm ) ;
11581176 card . style . cursor = 'pointer' ;
@@ -1284,6 +1302,7 @@ function accumulateInvertedNode(parent, stackFrame, leaf, isDifferential) {
12841302 if ( ! parent . children [ key ] ) {
12851303 const newNode = {
12861304 name : stackFrame . name ,
1305+ name_module : stackFrame . name_module ,
12871306 value : 0 ,
12881307 children : { } ,
12891308 filename : stackFrame . filename ,
@@ -1381,6 +1400,7 @@ function generateInvertedFlamegraph(data) {
13811400
13821401 const invertedRoot = {
13831402 name : data . name ,
1403+ name_module : data . name_module ,
13841404 value : data . value ,
13851405 children : { } ,
13861406 stats : data . stats ,
@@ -1405,6 +1425,19 @@ function toggleInvert() {
14051425 updateFlamegraphView ( ) ;
14061426}
14071427
1428+ function togglePathDisplay ( ) {
1429+ useModuleNames = ! useModuleNames ;
1430+ updateToggleUI ( 'toggle-path-display' , useModuleNames ) ;
1431+ const dataToRender = isInverted ? invertedData : normalData ;
1432+ const filteredData = currentThreadFilter !== 'all'
1433+ ? filterDataByThread ( dataToRender , parseInt ( currentThreadFilter ) )
1434+ : dataToRender ;
1435+
1436+ const tooltip = createPythonTooltip ( filteredData ) ;
1437+ const chart = createFlamegraph ( tooltip , filteredData . value ) ;
1438+ renderFlamegraph ( chart , filteredData ) ;
1439+ }
1440+
14081441// ============================================================================
14091442// Initialization
14101443// ============================================================================
@@ -1452,6 +1485,11 @@ function initFlamegraph() {
14521485 if ( toggleInvertBtn ) {
14531486 toggleInvertBtn . addEventListener ( 'click' , toggleInvert ) ;
14541487 }
1488+
1489+ const togglePathDisplayBtn = document . getElementById ( 'toggle-path-display' ) ;
1490+ if ( togglePathDisplayBtn ) {
1491+ togglePathDisplayBtn . addEventListener ( 'click' , togglePathDisplay ) ;
1492+ }
14551493}
14561494
14571495// Keyboard shortcut: Enter/Space activates toggle switches
0 commit comments