@@ -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) {
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+
89101// ============================================================================
90102// Theme & UI Controls
91103// ============================================================================
@@ -231,7 +243,8 @@ function updateStatusBar(nodeData, rootValue) {
231243
232244 const fileEl = document . getElementById ( 'status-file' ) ;
233245 if ( fileEl && filename && filename !== "~" ) {
234- fileEl . textContent = lineno ? `${ moduleName } :${ lineno } ` : moduleName ;
246+ const displayName = getDisplayName ( moduleName , filename ) ;
247+ fileEl . textContent = lineno ? `${ displayName } :${ lineno } ` : displayName ;
235248 }
236249
237250 const funcEl = document . getElementById ( 'status-func' ) ;
@@ -280,7 +293,8 @@ function createPythonTooltip(data) {
280293
281294 const funcname = resolveString ( d . data . funcname ) || resolveString ( d . data . name ) ;
282295 const filename = resolveString ( d . data . filename ) || "" ;
283- const moduleName = escapeHtml ( resolveString ( d . data . module_name ) || "" ) ;
296+ const moduleName = resolveString ( d . data . module_name ) || "" ;
297+ const displayName = escapeHtml ( getDisplayName ( moduleName , filename ) ) ;
284298 const isSpecialFrame = filename === "~" ;
285299
286300 // Build source section
@@ -349,7 +363,7 @@ function createPythonTooltip(data) {
349363 }
350364
351365 const fileLocationHTML = isSpecialFrame ? "" : `
352- <div class="tooltip-location">${ moduleName } ${ d . data . lineno ? ":" + d . data . lineno : "" } </div>` ;
366+ <div class="tooltip-location">${ displayName } ${ d . data . lineno ? ":" + d . data . lineno : "" } </div>` ;
353367
354368 const tooltipHTML = `
355369 <div class="tooltip-header">
@@ -479,6 +493,7 @@ function createFlamegraph(tooltip, rootValue) {
479493 . minFrameSize ( 1 )
480494 . tooltip ( tooltip )
481495 . inverted ( true )
496+ . getName ( d => resolveString ( useModuleNames ? d . data . name_module : d . data . name ) || resolveString ( d . data . name ) || '' )
482497 . setColorMapper ( function ( d ) {
483498 // Root node should be transparent
484499 if ( d . depth === 0 ) return 'transparent' ;
@@ -519,24 +534,24 @@ function updateSearchHighlight(searchTerm, searchInput) {
519534 const funcname = resolveString ( d . data . funcname ) || "" ;
520535 const filename = resolveString ( d . data . filename ) || "" ;
521536 const moduleName = resolveString ( d . data . module_name ) || "" ;
537+ const displayName = getDisplayName ( moduleName , filename ) ;
522538 const lineno = d . data . lineno ;
523539 const term = searchTerm . toLowerCase ( ) ;
524540
525- // Check if search term looks like module :line pattern
541+ // Check if search term looks like path :line pattern
526542 const fileLineMatch = term . match ( / ^ ( .+ ) : ( \d + ) $ / ) ;
527543 let matches = false ;
528544
529545 if ( fileLineMatch ) {
530546 const searchFile = fileLineMatch [ 1 ] ;
531547 const searchLine = parseInt ( fileLineMatch [ 2 ] , 10 ) ;
532- matches = moduleName . toLowerCase ( ) . includes ( searchFile ) && lineno === searchLine ;
548+ matches = displayName . toLowerCase ( ) . includes ( searchFile ) && lineno === searchLine ;
533549 } else {
534550 // Regular substring search
535551 matches =
536552 name . toLowerCase ( ) . includes ( term ) ||
537553 funcname . toLowerCase ( ) . includes ( term ) ||
538- moduleName . toLowerCase ( ) . includes ( term ) ||
539- filename . toLowerCase ( ) . includes ( term ) ;
554+ displayName . toLowerCase ( ) . includes ( term ) ;
540555 }
541556
542557 if ( matches ) {
@@ -988,7 +1003,8 @@ function populateStats(data) {
9881003 if ( isSpecialFrame ) {
9891004 fileEl . textContent = '--' ;
9901005 } else {
991- fileEl . textContent = `${ moduleName } :${ lineno } ` ;
1006+ const displayName = getDisplayName ( moduleName , filename ) ;
1007+ fileEl . textContent = `${ displayName } :${ lineno } ` ;
9921008 }
9931009 }
9941010 if ( percentEl ) percentEl . textContent = `${ h . directPercent . toFixed ( 1 ) } %` ;
@@ -1005,8 +1021,10 @@ function populateStats(data) {
10051021 if ( i < hotSpots . length && hotSpots [ i ] ) {
10061022 const h = hotSpots [ i ] ;
10071023 const moduleName = h . module_name || 'unknown' ;
1008- const hasValidLocation = moduleName !== 'unknown' && h . lineno !== '?' ;
1009- const searchTerm = hasValidLocation ? `${ moduleName } :${ h . lineno } ` : h . funcname ;
1024+ const filename = h . filename || 'unknown' ;
1025+ const displayName = getDisplayName ( moduleName , filename ) ;
1026+ const hasValidLocation = displayName !== 'unknown' && h . lineno !== '?' ;
1027+ const searchTerm = hasValidLocation ? `${ displayName } :${ h . lineno } ` : h . funcname ;
10101028 card . dataset . searchterm = searchTerm ;
10111029 card . onclick = ( ) => searchForHotspot ( searchTerm ) ;
10121030 card . style . cursor = 'pointer' ;
@@ -1158,6 +1176,7 @@ function accumulateInvertedNode(parent, stackFrame, leaf) {
11581176 if ( ! parent . children [ key ] ) {
11591177 parent . children [ key ] = {
11601178 name : stackFrame . name ,
1179+ name_module : stackFrame . name_module ,
11611180 value : 0 ,
11621181 children : { } ,
11631182 filename : stackFrame . filename ,
@@ -1220,6 +1239,7 @@ function convertInvertDictToArray(node) {
12201239function generateInvertedFlamegraph ( data ) {
12211240 const invertedRoot = {
12221241 name : data . name ,
1242+ name_module : data . name_module ,
12231243 value : data . value ,
12241244 children : { } ,
12251245 stats : data . stats ,
@@ -1258,6 +1278,19 @@ function toggleInvert() {
12581278 renderFlamegraph ( chart , dataToRender ) ;
12591279}
12601280
1281+ function togglePathDisplay ( ) {
1282+ useModuleNames = ! useModuleNames ;
1283+ updateToggleUI ( 'toggle-path-display' , useModuleNames ) ;
1284+ const dataToRender = isInverted ? invertedData : normalData ;
1285+ const filteredData = currentThreadFilter !== 'all'
1286+ ? filterDataByThread ( dataToRender , parseInt ( currentThreadFilter ) )
1287+ : dataToRender ;
1288+
1289+ const tooltip = createPythonTooltip ( filteredData ) ;
1290+ const chart = createFlamegraph ( tooltip , filteredData . value ) ;
1291+ renderFlamegraph ( chart , filteredData ) ;
1292+ }
1293+
12611294// ============================================================================
12621295// Initialization
12631296// ============================================================================
@@ -1293,6 +1326,11 @@ function initFlamegraph() {
12931326 if ( toggleInvertBtn ) {
12941327 toggleInvertBtn . addEventListener ( 'click' , toggleInvert ) ;
12951328 }
1329+
1330+ const togglePathDisplayBtn = document . getElementById ( 'toggle-path-display' ) ;
1331+ if ( togglePathDisplayBtn ) {
1332+ togglePathDisplayBtn . addEventListener ( 'click' , togglePathDisplay ) ;
1333+ }
12961334}
12971335
12981336// Keyboard shortcut: Enter/Space activates toggle switches
0 commit comments