@@ -99,13 +99,23 @@ function getDisplayName(moduleName, filename) {
9999 return filename ;
100100}
101101
102- function selectFlamegraphData ( ) {
103- const baseData = isShowingElided ? elidedFlamegraphData : normalData ;
102+ function selectFlamegraphData ( selectedThreadId = null ) {
103+ let baseData = isShowingElided ? elidedFlamegraphData : normalData ;
104+
105+ if ( selectedThreadId !== null ) {
106+ baseData = filterDataByThread ( baseData , selectedThreadId ) ;
107+ }
104108
105109 if ( ! isInverted ) {
106110 return baseData ;
107111 }
108112
113+ // Thread-filtered trees have different values, so invert them after filtering
114+ // instead of using the cached all-thread tree.
115+ if ( selectedThreadId !== null ) {
116+ return generateInvertedFlamegraph ( baseData ) ;
117+ }
118+
109119 if ( isShowingElided ) {
110120 if ( ! invertedElidedData ) {
111121 invertedElidedData = generateInvertedFlamegraph ( baseData ) ;
@@ -120,12 +130,11 @@ function selectFlamegraphData() {
120130}
121131
122132function updateFlamegraphView ( ) {
123- const selectedData = selectFlamegraphData ( ) ;
124133 const selectedThreadId = currentThreadFilter !== 'all' ? parseInt ( currentThreadFilter , 10 ) : null ;
125- const filteredData = selectedThreadId !== null ? filterDataByThread ( selectedData , selectedThreadId ) : selectedData ;
126- const tooltip = createPythonTooltip ( filteredData ) ;
127- const chart = createFlamegraph ( tooltip , filteredData . value , filteredData ) ;
128- renderFlamegraph ( chart , filteredData ) ;
134+ const selectedData = selectFlamegraphData ( selectedThreadId ) ;
135+ const tooltip = createPythonTooltip ( selectedData ) ;
136+ const chart = createFlamegraph ( tooltip , selectedData . value , selectedData ) ;
137+ renderFlamegraph ( chart , selectedData ) ;
129138 populateThreadStats ( selectedData , selectedThreadId ) ;
130139}
131140
@@ -937,7 +946,9 @@ function formatDuration(seconds) {
937946
938947function populateProfileSummary ( data ) {
939948 const stats = data . stats || { } ;
940- const totalSamples = stats . total_samples || data . value || 0 ;
949+ const totalSamples = currentThreadFilter !== 'all'
950+ ? ( data . value ?? 0 )
951+ : ( stats . total_samples ?? data . value ?? 0 ) ;
941952 const duration = stats . duration_sec || 0 ;
942953 const sampleRate = stats . sample_rate || ( duration > 0 ? totalSamples / duration : 0 ) ;
943954 const errorRate = stats . error_rate || 0 ;
@@ -1209,7 +1220,7 @@ function initThreadFilter(data) {
12091220 const threadFilter = document . getElementById ( 'thread-filter' ) ;
12101221 const threadSection = document . getElementById ( 'thread-section' ) ;
12111222
1212- if ( ! threadFilter || ! data . threads ) return ;
1223+ if ( ! threadFilter || ! data . threads || data . stats ?. is_differential ) return ;
12131224
12141225 threadFilter . innerHTML = '<option value="all">All Threads</option>' ;
12151226
@@ -1238,11 +1249,23 @@ function filterByThread() {
12381249
12391250function filterDataByThread ( data , threadId ) {
12401251 function filterNode ( node ) {
1241- if ( ! node . threads || ! node . threads . includes ( threadId ) ) {
1252+ const threadValues = node . thread_values ?. [ threadId ] ;
1253+ if ( ! threadValues ) {
12421254 return null ;
12431255 }
12441256
1245- const filteredNode = { ...node , children : [ ] } ;
1257+ const {
1258+ thread_values : _threadValues ,
1259+ thread_opcodes : threadOpcodes ,
1260+ ...sharedNode
1261+ } = node ;
1262+ const filteredNode = {
1263+ ...sharedNode ,
1264+ value : threadValues [ 0 ] ,
1265+ self : threadValues [ 1 ] ,
1266+ opcodes : threadOpcodes ?. [ threadId ] ?? { } ,
1267+ children : [ ]
1268+ } ;
12461269
12471270 if ( node . children && Array . isArray ( node . children ) ) {
12481271 filteredNode . children = node . children
@@ -1253,25 +1276,7 @@ function filterDataByThread(data, threadId) {
12531276 return filteredNode ;
12541277 }
12551278
1256- function recalculateValue ( node ) {
1257- if ( ! node . children || node . children . length === 0 ) {
1258- return node . value || 0 ;
1259- }
1260- const childrenValue = node . children . reduce ( ( sum , child ) => sum + recalculateValue ( child ) , 0 ) ;
1261- node . value = Math . max ( node . value || 0 , childrenValue ) ;
1262- return node . value ;
1263- }
1264-
1265- const filteredRoot = { ...data , children : [ ] } ;
1266-
1267- if ( data . children && Array . isArray ( data . children ) ) {
1268- filteredRoot . children = data . children
1269- . map ( child => filterNode ( child ) )
1270- . filter ( child => child !== null ) ;
1271- }
1272-
1273- recalculateValue ( filteredRoot ) ;
1274- return filteredRoot ;
1279+ return filterNode ( data ) ;
12751280}
12761281
12771282// ============================================================================
0 commit comments