@@ -25,11 +25,13 @@ import {
2525import {
2626 getAllCommittedRanges ,
2727 getSelectedThreadIndexes ,
28+ getTransformStack ,
2829} from 'firefox-profiler/selectors/url-state' ;
2930import {
3031 commitRange ,
3132 popCommittedRanges ,
3233 changeSelectedThreads ,
34+ addTransformToStack ,
3335} from '../actions/profile-view' ;
3436import { getThreadSelectors } from 'firefox-profiler/selectors/per-thread' ;
3537import { TimestampManager } from './timestamps' ;
@@ -72,7 +74,8 @@ import type {
7274} from './types' ;
7375import type { CallTreeCollectionOptions } from './formatters/call-tree' ;
7476
75- import type { StartEndRange } from 'firefox-profiler/types' ;
77+ import { getThreadsKey } from 'firefox-profiler/profile-logic/profile-data' ;
78+ import type { StartEndRange , ThreadIndex } from 'firefox-profiler/types' ;
7679import type { Store } from '../types/store' ;
7780
7881export class ProfileQuerier {
@@ -133,43 +136,73 @@ export class ProfileQuerier {
133136 }
134137
135138 async threadSamples (
136- threadHandle ?: string
139+ threadHandle ?: string ,
140+ includeIdle : boolean = false
137141 ) : Promise < WithContext < ThreadSamplesResult > > {
138- const result = await collectThreadSamples (
139- this . _store ,
140- this . _threadMap ,
141- this . _functionMap ,
142- threadHandle
143- ) ;
144- return { ...result , context : this . _getContext ( ) } ;
142+ const activeOnly = ! includeIdle ;
143+ const threadIndexes =
144+ threadHandle !== undefined
145+ ? this . _threadMap . threadIndexesForHandle ( threadHandle )
146+ : getSelectedThreadIndexes ( this . _store . getState ( ) ) ;
147+ const collect = ( ) =>
148+ collectThreadSamples (
149+ this . _store ,
150+ this . _threadMap ,
151+ this . _functionMap ,
152+ threadHandle
153+ ) ;
154+ const result = activeOnly
155+ ? this . _withDroppedIdle ( threadIndexes , collect )
156+ : collect ( ) ;
157+ return { ...result , activeOnly, context : this . _getContext ( ) } ;
145158 }
146159
147160 async threadSamplesTopDown (
148161 threadHandle ?: string ,
149- callTreeOptions ?: CallTreeCollectionOptions
162+ callTreeOptions ?: CallTreeCollectionOptions ,
163+ includeIdle : boolean = false
150164 ) : Promise < WithContext < ThreadSamplesTopDownResult > > {
151- const result = await collectThreadSamplesTopDown (
152- this . _store ,
153- this . _threadMap ,
154- this . _functionMap ,
155- threadHandle ,
156- callTreeOptions
157- ) ;
158- return { ...result , context : this . _getContext ( ) } ;
165+ const activeOnly = ! includeIdle ;
166+ const threadIndexes =
167+ threadHandle !== undefined
168+ ? this . _threadMap . threadIndexesForHandle ( threadHandle )
169+ : getSelectedThreadIndexes ( this . _store . getState ( ) ) ;
170+ const collect = ( ) =>
171+ collectThreadSamplesTopDown (
172+ this . _store ,
173+ this . _threadMap ,
174+ this . _functionMap ,
175+ threadHandle ,
176+ callTreeOptions
177+ ) ;
178+ const result = activeOnly
179+ ? this . _withDroppedIdle ( threadIndexes , collect )
180+ : collect ( ) ;
181+ return { ...result , activeOnly, context : this . _getContext ( ) } ;
159182 }
160183
161184 async threadSamplesBottomUp (
162185 threadHandle ?: string ,
163- callTreeOptions ?: CallTreeCollectionOptions
186+ callTreeOptions ?: CallTreeCollectionOptions ,
187+ includeIdle : boolean = false
164188 ) : Promise < WithContext < ThreadSamplesBottomUpResult > > {
165- const result = await collectThreadSamplesBottomUp (
166- this . _store ,
167- this . _threadMap ,
168- this . _functionMap ,
169- threadHandle ,
170- callTreeOptions
171- ) ;
172- return { ...result , context : this . _getContext ( ) } ;
189+ const activeOnly = ! includeIdle ;
190+ const threadIndexes =
191+ threadHandle !== undefined
192+ ? this . _threadMap . threadIndexesForHandle ( threadHandle )
193+ : getSelectedThreadIndexes ( this . _store . getState ( ) ) ;
194+ const collect = ( ) =>
195+ collectThreadSamplesBottomUp (
196+ this . _store ,
197+ this . _threadMap ,
198+ this . _functionMap ,
199+ threadHandle ,
200+ callTreeOptions
201+ ) ;
202+ const result = activeOnly
203+ ? this . _withDroppedIdle ( threadIndexes , collect )
204+ : collect ( ) ;
205+ return { ...result , activeOnly, context : this . _getContext ( ) } ;
173206 }
174207
175208 /**
@@ -397,6 +430,42 @@ export class ProfileQuerier {
397430 return `Selected ${ threadIndexes . size } threads: ${ threadHandle } (${ names } )` ;
398431 }
399432
433+ /**
434+ * Apply a drop-category transform for the Idle category around a computation,
435+ * then restore the transform stack to its previous state.
436+ * If the profile has no Idle category, fn() is called without changes.
437+ */
438+ private _withDroppedIdle < T > ( threadIndexes : Set < ThreadIndex > , fn : ( ) => T ) : T {
439+ const state = this . _store . getState ( ) ;
440+ const profile = getProfile ( state ) ;
441+ const idleCategoryIndex =
442+ profile . meta . categories ?. findIndex ( ( c ) => c . name === 'Idle' ) ?? - 1 ;
443+
444+ if ( idleCategoryIndex === - 1 ) {
445+ return fn ( ) ;
446+ }
447+
448+ const threadsKey = getThreadsKey ( threadIndexes ) ;
449+ const stackLengthBefore = getTransformStack ( state , threadsKey ) . length ;
450+
451+ this . _store . dispatch (
452+ addTransformToStack ( threadsKey , {
453+ type : 'drop-category' ,
454+ category : idleCategoryIndex ,
455+ } )
456+ ) ;
457+
458+ try {
459+ return fn ( ) ;
460+ } finally {
461+ this . _store . dispatch ( {
462+ type : 'POP_TRANSFORMS_FROM_STACK' ,
463+ threadsKey,
464+ firstPoppedFilterIndex : stackLengthBefore ,
465+ } ) ;
466+ }
467+ }
468+
400469 /**
401470 * Get current session context for display in command outputs.
402471 * This is a lightweight version of getStatus() that includes only
@@ -643,16 +712,26 @@ export class ProfileQuerier {
643712 */
644713 async threadFunctions (
645714 threadHandle ?: string ,
646- filterOptions ?: FunctionFilterOptions
715+ filterOptions ?: FunctionFilterOptions ,
716+ includeIdle : boolean = false
647717 ) : Promise < WithContext < ThreadFunctionsResult > > {
648- const result = await collectThreadFunctions (
649- this . _store ,
650- this . _threadMap ,
651- this . _functionMap ,
652- threadHandle ,
653- filterOptions
654- ) ;
655- return { ...result , context : this . _getContext ( ) } ;
718+ const activeOnly = ! includeIdle ;
719+ const threadIndexes =
720+ threadHandle !== undefined
721+ ? this . _threadMap . threadIndexesForHandle ( threadHandle )
722+ : getSelectedThreadIndexes ( this . _store . getState ( ) ) ;
723+ const collect = ( ) =>
724+ collectThreadFunctions (
725+ this . _store ,
726+ this . _threadMap ,
727+ this . _functionMap ,
728+ threadHandle ,
729+ filterOptions
730+ ) ;
731+ const result = activeOnly
732+ ? this . _withDroppedIdle ( threadIndexes , collect )
733+ : collect ( ) ;
734+ return { ...result , activeOnly, context : this . _getContext ( ) } ;
656735 }
657736
658737 /**
0 commit comments