@@ -11,7 +11,7 @@ import {data as layerTreeHandlerData, type LayerTreeData} from './LayerTreeHandl
1111import { data as metaHandlerData , type MetaHandlerData } from './MetaHandler.js' ;
1212import { data as rendererHandlerData , type RendererHandlerData } from './RendererHandler.js' ;
1313import * as Threads from './Threads.js' ;
14- import type { FinalizeOptions , HandlerName } from './types.js' ;
14+ import type { HandlerName } from './types.js' ;
1515
1616/**
1717 * IMPORTANT: this handler is slightly different to the rest. This is because
@@ -25,22 +25,61 @@ import type {FinalizeOptions, HandlerName} from './types.js';
2525 */
2626
2727let model : TimelineFrameModel | null = null ;
28+ const relevantFrameEvents : Types . Events . Event [ ] = [ ] ;
29+
30+ type FrameEvent = Types . Events . BeginFrame | Types . Events . DroppedFrame | Types . Events . RequestMainThreadFrame |
31+ Types . Events . BeginMainThreadFrame | Types . Events . Commit | Types . Events . CompositeLayers |
32+ Types . Events . ActivateLayerTree | Types . Events . NeedsBeginFrameChanged | Types . Events . DrawFrame ;
33+
34+ function isFrameEvent ( event : Types . Events . Event ) : event is FrameEvent {
35+ return (
36+ Types . Events . isSetLayerId ( event ) || Types . Events . isBeginFrame ( event ) || Types . Events . isDroppedFrame ( event ) ||
37+ Types . Events . isRequestMainThreadFrame ( event ) || Types . Events . isBeginMainThreadFrame ( event ) ||
38+ Types . Events . isNeedsBeginFrameChanged ( event ) ||
39+ // Note that "Commit" is the replacement for "CompositeLayers" so in a trace
40+ // we wouldn't expect to see a combination of these. All "new" trace
41+ // recordings use "Commit", but we can easily support "CompositeLayers" too
42+ // to not break older traces being imported.
43+ Types . Events . isCommit ( event ) || Types . Events . isCompositeLayers ( event ) ||
44+ Types . Events . isActivateLayerTree ( event ) || Types . Events . isDrawFrame ( event ) ) ;
45+ }
46+
47+ function entryIsTopLevel ( entry : Types . Events . Event ) : boolean {
48+ const devtoolsTimelineCategory = 'disabled-by-default-devtools.timeline' ;
49+ return entry . name === Types . Events . Name . RUN_TASK && entry . cat . includes ( devtoolsTimelineCategory ) ;
50+ }
51+
52+ const MAIN_FRAME_MARKERS = new Set < Types . Events . Name > ( [
53+ Types . Events . Name . SCHEDULE_STYLE_RECALCULATION ,
54+ Types . Events . Name . INVALIDATE_LAYOUT ,
55+ Types . Events . Name . BEGIN_MAIN_THREAD_FRAME ,
56+ Types . Events . Name . SCROLL_LAYER ,
57+ ] ) ;
2858
2959export function reset ( ) : void {
3060 model = null ;
61+ relevantFrameEvents . length = 0 ;
3162}
32- export function handleEvent ( ) : void {
63+ export function handleEvent ( event : Types . Events . Event ) : void {
64+ // This might seem like a wide set of events to filter for, but these are all
65+ // the types of events that we care about in the TimelineFrameModel class at
66+ // the bottom of this file. Previously we would take a copy of an array of
67+ // all trace events, but on a few test traces, this set of filtered events
68+ // accounts for about 10% of the total events, so it's a big performance win
69+ // to deal with a much smaller subset of the data.
70+ if ( isFrameEvent ( event ) || Types . Events . isLayerTreeHostImplSnapshot ( event ) || entryIsTopLevel ( event ) ||
71+ MAIN_FRAME_MARKERS . has ( event . name as Types . Events . Name ) || Types . Events . isPaint ( event ) ) {
72+ relevantFrameEvents . push ( event ) ;
73+ }
3374}
3475
35- export async function finalize ( { allTraceEvents} : FinalizeOptions ) : Promise < void > {
36- // Snapshot events can be emitted out of order, so we need to sort before
37- // building the frames model, but we need to take a copy because we don't
38- // can't mutate the raw input.
39- // TODO(crbug.com/436491188): this is expensive...we copy and sort the entire trace each time we import it.
40- const allEvents = allTraceEvents . toSorted ( Helpers . Trace . eventTimeComparator ) ;
76+ export async function finalize ( ) : Promise < void > {
77+ // We have to sort the events by timestamp, because the model code expects to
78+ // process events in order.
79+ Helpers . Trace . sortTraceEventsInPlace ( relevantFrameEvents ) ;
4180
4281 const modelForTrace = new TimelineFrameModel (
43- allEvents ,
82+ relevantFrameEvents ,
4483 rendererHandlerData ( ) ,
4584 auctionWorkletsData ( ) ,
4685 metaHandlerData ( ) ,
@@ -65,28 +104,6 @@ export function deps(): HandlerName[] {
65104 return [ 'Meta' , 'Renderer' , 'AuctionWorklets' , 'LayerTree' ] ;
66105}
67106
68- type FrameEvent = Types . Events . BeginFrame | Types . Events . DroppedFrame | Types . Events . RequestMainThreadFrame |
69- Types . Events . BeginMainThreadFrame | Types . Events . Commit | Types . Events . CompositeLayers |
70- Types . Events . ActivateLayerTree | Types . Events . NeedsBeginFrameChanged | Types . Events . DrawFrame ;
71-
72- function isFrameEvent ( event : Types . Events . Event ) : event is FrameEvent {
73- return (
74- Types . Events . isSetLayerId ( event ) || Types . Events . isBeginFrame ( event ) || Types . Events . isDroppedFrame ( event ) ||
75- Types . Events . isRequestMainThreadFrame ( event ) || Types . Events . isBeginMainThreadFrame ( event ) ||
76- Types . Events . isNeedsBeginFrameChanged ( event ) ||
77- // Note that "Commit" is the replacement for "CompositeLayers" so in a trace
78- // we wouldn't expect to see a combination of these. All "new" trace
79- // recordings use "Commit", but we can easily support "CompositeLayers" too
80- // to not break older traces being imported.
81- Types . Events . isCommit ( event ) || Types . Events . isCompositeLayers ( event ) ||
82- Types . Events . isActivateLayerTree ( event ) || Types . Events . isDrawFrame ( event ) ) ;
83- }
84-
85- function entryIsTopLevel ( entry : Types . Events . Event ) : boolean {
86- const devtoolsTimelineCategory = 'disabled-by-default-devtools.timeline' ;
87- return entry . name === Types . Events . Name . RUN_TASK && entry . cat . includes ( devtoolsTimelineCategory ) ;
88- }
89-
90107export class TimelineFrameModel {
91108 #frames: TimelineFrame [ ] = [ ] ;
92109 #frameById: Record < number , TimelineFrame > = { } ;
@@ -362,13 +379,6 @@ export class TimelineFrameModel {
362379 }
363380}
364381
365- const MAIN_FRAME_MARKERS = new Set < Types . Events . Name > ( [
366- Types . Events . Name . SCHEDULE_STYLE_RECALCULATION ,
367- Types . Events . Name . INVALIDATE_LAYOUT ,
368- Types . Events . Name . BEGIN_MAIN_THREAD_FRAME ,
369- Types . Events . Name . SCROLL_LAYER ,
370- ] ) ;
371-
372382/**
373383 * Legacy class that represents TimelineFrames that was ported from the old SDK.
374384 * This class is purposefully not exported as it breaks the abstraction that
0 commit comments