@@ -27,13 +27,11 @@ import type {
2727} from 'firefox-profiler/profile-logic/benchmark/perf-compare-stats' ;
2828import type { Profile } from 'firefox-profiler/types' ;
2929import { BucketFlameGraphPair } from './BucketFlameGraphPair' ;
30- import type { BucketProfileBundle } from './BucketFlameGraphPair' ;
3130import {
32- buildDerivedThread ,
33- getCategoriesForProfile ,
34- getDefaultCategoryIndex ,
31+ makeBucketProfileBundle ,
32+ makeSuiteFilteredThread ,
3533} from 'firefox-profiler/profile-logic/benchmark/bucket-flame-graph-data' ;
36- import { getBenchmarkInfo } from 'firefox-profiler/profile-logic/benchmark/benchmark-stuff ' ;
34+ import type { BucketProfileBundle } from 'firefox-profiler/profile-logic/benchmark/bucket-flame-graph-data ' ;
3735import './BenchmarkCompareViewer.css' ;
3836
3937type ComparisonData = {
@@ -286,17 +284,10 @@ function ScoreTable({
286284 </ thead >
287285 < tbody >
288286 < tr className = "benchmarkRow--overall" >
289- < td
290- className = "benchmarkCell--scoreLabel"
291- title = { overallScore . label }
292- >
287+ < td className = "benchmarkCell--scoreLabel" title = { overallScore . label } >
293288 { overallScore . label }
294289 </ td >
295- < ScoreRow
296- row = { overallScore }
297- isOverall = { true }
298- numSuites = { numSuites }
299- />
290+ < ScoreRow row = { overallScore } isOverall = { true } numSuites = { numSuites } />
300291 </ tr >
301292 { suiteScores . map ( ( row ) => {
302293 const isExpanded = expanded . has ( row . label ) ;
@@ -315,10 +306,7 @@ function ScoreTable({
315306 title = { row . label }
316307 >
317308 { expandable && (
318- < span
319- className = "benchmarkDisclosure"
320- aria-hidden = "true"
321- >
309+ < span className = "benchmarkDisclosure" aria-hidden = "true" >
322310 { isExpanded ? '▼' : '▶' }
323311 </ span >
324312 ) }
@@ -369,6 +357,18 @@ function BucketTable({
369357 baseSubtestMean !== undefined && numSuites !== undefined ;
370358 const columnCount = showSubtestColumns ? 6 : 5 ;
371359
360+ // Build per-suite bundles whose `thread.samples.weight` is zeroed outside
361+ // this suite's iteration markers, so flame graphs reflect only the samples
362+ // that contribute to this suite's score.
363+ const baseSuiteBundle = useMemo (
364+ ( ) => withSuiteFilteredThread ( baseBundle , label ) ,
365+ [ baseBundle , label ]
366+ ) ;
367+ const newSuiteBundle = useMemo (
368+ ( ) => withSuiteFilteredThread ( newBundle , label ) ,
369+ [ newBundle , label ]
370+ ) ;
371+
372372 const [ expanded , setExpanded ] = useState < Set < string > > ( new Set ( ) ) ;
373373 const toggle = ( bucketName : string ) => {
374374 setExpanded ( ( prev ) => {
@@ -380,7 +380,7 @@ function BucketTable({
380380 } ;
381381
382382 const significant = comparisons
383- . filter ( ( c ) => c . confidence !== 'LOW' && c . effectSize !== 'Negligible' )
383+ // .filter((c) => c.confidence !== 'LOW' && c.effectSize !== 'Negligible')
384384 . sort (
385385 ( a , b ) =>
386386 Math . abs ( b . newMean - b . baseMean ) - Math . abs ( a . newMean - a . baseMean )
@@ -465,16 +465,18 @@ function BucketTable({
465465 < td className = "benchmarkCell--number" >
466466 { c . baseMean . toFixed ( 2 ) }
467467 </ td >
468- < td className = "benchmarkCell--number" > { c . newMean . toFixed ( 2 ) } </ td >
468+ < td className = "benchmarkCell--number" >
469+ { c . newMean . toFixed ( 2 ) }
470+ </ td >
469471 < td className = "benchmarkCell--number" > { absDiffStr } </ td >
470472 { pctCells }
471473 </ tr >
472474 { expandable && isExpanded && (
473475 < tr className = "benchmarkRow--bucket-expansion" >
474476 < td colSpan = { columnCount } >
475477 < BucketFlameGraphPair
476- baseBundle = { baseBundle }
477- newBundle = { newBundle }
478+ baseBundle = { baseSuiteBundle }
479+ newBundle = { newSuiteBundle }
478480 baseFunc = { c . baseFunc }
479481 newFunc = { c . newFunc }
480482 />
@@ -489,20 +491,14 @@ function BucketTable({
489491 ) ;
490492}
491493
492- /** Build the (profile, derivedThread, categories) bundle once per profile.
493- * Computing the derived thread is expensive, so we memoize on profile identity
494- * and reuse the same bundle across every bucket the user expands. */
495- function makeBucketProfileBundle ( profile : Profile ) : BucketProfileBundle {
496- const categories = getCategoriesForProfile ( profile ) ;
497- const defaultCategory = getDefaultCategoryIndex ( categories ) ;
498- const benchmarkInfo = getBenchmarkInfo ( profile , 'speedometer' ) ;
499- const thread = buildDerivedThread (
500- profile ,
501- benchmarkInfo . threadIndex ,
502- categories ,
503- defaultCategory
504- ) ;
505- return { profile, thread, categories, defaultCategory } ;
494+ /** Return a copy of `bundle` whose `thread` has sample weights zeroed outside
495+ * this suite's iteration markers (matching the filtering applied to the suite
496+ * count). All other bundle fields are shared with the input. */
497+ function withSuiteFilteredThread (
498+ bundle : BucketProfileBundle ,
499+ suiteName : string
500+ ) : BucketProfileBundle {
501+ return { ...bundle , thread : makeSuiteFilteredThread ( bundle , suiteName ) } ;
506502}
507503
508504function ComparisonResults ( { data } : { data : ComparisonData } ) {
@@ -514,11 +510,11 @@ function ComparisonResults({ data }: { data: ComparisonData }) {
514510 ) ;
515511
516512 const baseBundle = useMemo (
517- ( ) => makeBucketProfileBundle ( data . baseProfile ) ,
513+ ( ) => makeBucketProfileBundle ( data . baseProfile , 'speedometer' ) ,
518514 [ data . baseProfile ]
519515 ) ;
520516 const newBundle = useMemo (
521- ( ) => makeBucketProfileBundle ( data . newProfile ) ,
517+ ( ) => makeBucketProfileBundle ( data . newProfile , 'speedometer' ) ,
522518 [ data . newProfile ]
523519 ) ;
524520
0 commit comments