@@ -693,16 +693,35 @@ function populateProfileSummary(data) {
693693 if ( rateEl ) rateEl . textContent = sampleRate > 0 ? formatNumber ( Math . round ( sampleRate ) ) : '--' ;
694694
695695 // Count unique functions
696- let functionCount = 0 ;
697- function countFunctions ( node ) {
696+ // Use normal (non-inverted) tree structure, but respect thread filtering
697+ const uniqueFunctions = new Set ( ) ;
698+ function collectUniqueFunctions ( node ) {
698699 if ( ! node ) return ;
699- functionCount ++ ;
700- if ( node . children ) node . children . forEach ( countFunctions ) ;
700+ const filename = resolveString ( node . filename ) || 'unknown' ;
701+ const funcname = resolveString ( node . funcname ) || resolveString ( node . name ) || 'unknown' ;
702+ const lineno = node . lineno || 0 ;
703+ const key = `${ filename } |${ lineno } |${ funcname } ` ;
704+ uniqueFunctions . add ( key ) ;
705+ if ( node . children ) node . children . forEach ( collectUniqueFunctions ) ;
701706 }
702- countFunctions ( data ) ;
707+ // In inverted mode, use normalData (with thread filter if active)
708+ // In normal mode, use the passed data (already has thread filter applied if any)
709+ let functionCountSource ;
710+ if ( ! normalData ) {
711+ functionCountSource = data ;
712+ } else if ( isInverted ) {
713+ if ( currentThreadFilter !== 'all' ) {
714+ functionCountSource = filterDataByThread ( normalData , parseInt ( currentThreadFilter ) ) ;
715+ } else {
716+ functionCountSource = normalData ;
717+ }
718+ } else {
719+ functionCountSource = data ;
720+ }
721+ collectUniqueFunctions ( functionCountSource ) ;
703722
704723 const functionsEl = document . getElementById ( 'stat-functions' ) ;
705- if ( functionsEl ) functionsEl . textContent = formatNumber ( functionCount ) ;
724+ if ( functionsEl ) functionsEl . textContent = formatNumber ( uniqueFunctions . size ) ;
706725
707726 // Efficiency bar
708727 if ( errorRate !== undefined && errorRate !== null ) {
@@ -737,14 +756,31 @@ function populateProfileSummary(data) {
737756// ============================================================================
738757
739758function populateStats ( data ) {
740- const totalSamples = data . value || 0 ;
741-
742759 // Populate profile summary
743760 populateProfileSummary ( data ) ;
744761
745762 // Populate thread statistics if available
746763 populateThreadStats ( data ) ;
747764
765+ // For hotspots: use normal (non-inverted) tree structure, but respect thread filtering.
766+ // In inverted view, the tree structure changes but the hottest functions remain the same.
767+ // However, if a thread filter is active, we need to show that thread's hotspots.
768+ let hotspotSource ;
769+ if ( ! normalData ) {
770+ hotspotSource = data ;
771+ } else if ( isInverted ) {
772+ // In inverted mode, use normalData (with thread filter if active)
773+ if ( currentThreadFilter !== 'all' ) {
774+ hotspotSource = filterDataByThread ( normalData , parseInt ( currentThreadFilter ) ) ;
775+ } else {
776+ hotspotSource = normalData ;
777+ }
778+ } else {
779+ // In normal mode, use the passed data (already has thread filter applied if any)
780+ hotspotSource = data ;
781+ }
782+ const totalSamples = hotspotSource . value || 0 ;
783+
748784 const functionMap = new Map ( ) ;
749785
750786 function collectFunctions ( node ) {
@@ -802,7 +838,7 @@ function populateStats(data) {
802838 }
803839 }
804840
805- collectFunctions ( data ) ;
841+ collectFunctions ( hotspotSource ) ;
806842
807843 const hotSpots = Array . from ( functionMap . values ( ) )
808844 . filter ( f => f . directPercent > 0.5 )
0 commit comments