@@ -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' ) ;
@@ -309,7 +322,8 @@ function createPythonTooltip(data) {
309322
310323 const funcname = resolveString ( d . data . funcname ) || resolveString ( d . data . name ) ;
311324 const filename = resolveString ( d . data . filename ) || "" ;
312- const moduleName = escapeHtml ( resolveString ( d . data . module_name ) || "" ) ;
325+ const moduleName = resolveString ( d . data . module_name ) || "" ;
326+ const displayName = escapeHtml ( useModuleNames ? ( moduleName || filename ) : filename ) ;
313327 const isSpecialFrame = filename === "~" ;
314328
315329 // Build source section
@@ -378,7 +392,7 @@ function createPythonTooltip(data) {
378392 }
379393
380394 const fileLocationHTML = isSpecialFrame ? "" : `
381- <div class="tooltip-location">${ moduleName } ${ d . data . lineno ? ":" + d . data . lineno : "" } </div>` ;
395+ <div class="tooltip-location">${ displayName } ${ d . data . lineno ? ":" + d . data . lineno : "" } </div>` ;
382396
383397 // Differential stats section
384398 let diffSection = "" ;
@@ -595,6 +609,7 @@ function createFlamegraph(tooltip, rootValue, data) {
595609 . minFrameSize ( 1 )
596610 . tooltip ( tooltip )
597611 . inverted ( true )
612+ . getName ( d => resolveString ( useModuleNames ? d . data . name_module : d . data . name ) || resolveString ( d . data . name ) || '' )
598613 . setColorMapper ( function ( d ) {
599614 if ( d . depth === 0 ) return 'transparent' ;
600615
@@ -638,24 +653,24 @@ function updateSearchHighlight(searchTerm, searchInput) {
638653 const funcname = resolveString ( d . data . funcname ) || "" ;
639654 const filename = resolveString ( d . data . filename ) || "" ;
640655 const moduleName = resolveString ( d . data . module_name ) || "" ;
656+ const displayName = getDisplayName ( moduleName , filename ) ;
641657 const lineno = d . data . lineno ;
642658 const term = searchTerm . toLowerCase ( ) ;
643659
644- // Check if search term looks like module :line pattern
660+ // Check if search term looks like path :line pattern
645661 const fileLineMatch = term . match ( / ^ ( .+ ) : ( \d + ) $ / ) ;
646662 let matches = false ;
647663
648664 if ( fileLineMatch ) {
649665 const searchFile = fileLineMatch [ 1 ] ;
650666 const searchLine = parseInt ( fileLineMatch [ 2 ] , 10 ) ;
651- matches = moduleName . toLowerCase ( ) . includes ( searchFile ) && lineno === searchLine ;
667+ matches = displayName . toLowerCase ( ) . includes ( searchFile ) && lineno === searchLine ;
652668 } else {
653669 // Regular substring search
654670 matches =
655671 name . toLowerCase ( ) . includes ( term ) ||
656672 funcname . toLowerCase ( ) . includes ( term ) ||
657- moduleName . toLowerCase ( ) . includes ( term ) ||
658- filename . toLowerCase ( ) . includes ( term ) ;
673+ displayName . toLowerCase ( ) . includes ( term ) ;
659674 }
660675
661676 if ( matches ) {
@@ -1141,7 +1156,8 @@ function populateStats(data) {
11411156 if ( isSpecialFrame ) {
11421157 fileEl . textContent = '--' ;
11431158 } else {
1144- fileEl . textContent = `${ moduleName } :${ lineno } ` ;
1159+ const displayName = getDisplayName ( moduleName , filename ) ;
1160+ fileEl . textContent = `${ displayName } :${ lineno } ` ;
11451161 }
11461162 }
11471163 if ( percentEl ) percentEl . textContent = `${ h . directPercent . toFixed ( 1 ) } %` ;
@@ -1158,8 +1174,10 @@ function populateStats(data) {
11581174 if ( i < hotSpots . length && hotSpots [ i ] ) {
11591175 const h = hotSpots [ i ] ;
11601176 const moduleName = h . module_name || 'unknown' ;
1161- const hasValidLocation = moduleName !== 'unknown' && h . lineno !== '?' ;
1162- const searchTerm = hasValidLocation ? `${ moduleName } :${ h . lineno } ` : h . funcname ;
1177+ const filename = h . filename || 'unknown' ;
1178+ const displayName = getDisplayName ( moduleName , filename ) ;
1179+ const hasValidLocation = displayName !== 'unknown' && h . lineno !== '?' ;
1180+ const searchTerm = hasValidLocation ? `${ displayName } :${ h . lineno } ` : h . funcname ;
11631181 card . dataset . searchterm = searchTerm ;
11641182 card . onclick = ( ) => searchForHotspot ( searchTerm ) ;
11651183 card . style . cursor = 'pointer' ;
@@ -1291,6 +1309,7 @@ function accumulateInvertedNode(parent, stackFrame, leaf, isDifferential) {
12911309 if ( ! parent . children [ key ] ) {
12921310 const newNode = {
12931311 name : stackFrame . name ,
1312+ name_module : stackFrame . name_module ,
12941313 value : 0 ,
12951314 self : 0 ,
12961315 children : { } ,
@@ -1390,6 +1409,7 @@ function generateInvertedFlamegraph(data) {
13901409
13911410 const invertedRoot = {
13921411 name : data . name ,
1412+ name_module : data . name_module ,
13931413 value : data . value ,
13941414 children : { } ,
13951415 stats : data . stats ,
@@ -1414,6 +1434,19 @@ function toggleInvert() {
14141434 updateFlamegraphView ( ) ;
14151435}
14161436
1437+ function togglePathDisplay ( ) {
1438+ useModuleNames = ! useModuleNames ;
1439+ updateToggleUI ( 'toggle-path-display' , useModuleNames ) ;
1440+ const dataToRender = isInverted ? invertedData : normalData ;
1441+ const filteredData = currentThreadFilter !== 'all'
1442+ ? filterDataByThread ( dataToRender , parseInt ( currentThreadFilter ) )
1443+ : dataToRender ;
1444+
1445+ const tooltip = createPythonTooltip ( filteredData ) ;
1446+ const chart = createFlamegraph ( tooltip , filteredData . value ) ;
1447+ renderFlamegraph ( chart , filteredData ) ;
1448+ }
1449+
14171450// ============================================================================
14181451// Initialization
14191452// ============================================================================
@@ -1461,6 +1494,11 @@ function initFlamegraph() {
14611494 if ( toggleInvertBtn ) {
14621495 toggleInvertBtn . addEventListener ( 'click' , toggleInvert ) ;
14631496 }
1497+
1498+ const togglePathDisplayBtn = document . getElementById ( 'toggle-path-display' ) ;
1499+ if ( togglePathDisplayBtn ) {
1500+ togglePathDisplayBtn . addEventListener ( 'click' , togglePathDisplay ) ;
1501+ }
14641502}
14651503
14661504// Keyboard shortcut: Enter/Space activates toggle switches
0 commit comments