@@ -8,12 +8,31 @@ import type {
8
8
MarkerIndex ,
9
9
MarkerTiming ,
10
10
MarkerTimingAndBuckets ,
11
+ MarkerSchemaByName ,
11
12
} from 'firefox-profiler/types' ;
12
13
14
+ import { getSchemaFromMarker } from './marker-schema' ;
15
+
13
16
// Arbitrarily set an upper limit for adding marker depths, avoiding very long
14
17
// overlapping marker timings.
15
18
const MAX_STACKING_DEPTH = 300 ;
16
19
20
+ function _createEmptyTiming (
21
+ name : string ,
22
+ bucket : string ,
23
+ instantOnly : boolean
24
+ ) : MarkerTiming {
25
+ return {
26
+ start : [ ] ,
27
+ end : [ ] ,
28
+ index : [ ] ,
29
+ name,
30
+ bucket,
31
+ instantOnly,
32
+ length : 0 ,
33
+ } ;
34
+ }
35
+
17
36
/**
18
37
* This function computes the timing information for laying out the markers in the
19
38
* MarkerChart component. Each marker is put into a single row based on its name. In
@@ -86,13 +105,15 @@ export function getMarkerTiming(
86
105
markerIndexes : MarkerIndex [ ] ,
87
106
// Categories can be null for things like Network Markers, where we don't care to
88
107
// break things up by category.
89
- categories : ?CategoryList
108
+ categories : ?CategoryList ,
109
+ markerSchemaByName : ?MarkerSchemaByName
90
110
) : MarkerTiming [ ] {
91
- // Each marker type will have it's own timing information, later collapse these into
111
+ // Each marker type will have its own timing information, later collapse these into
92
112
// a single array.
93
113
const intervalMarkerTimingsMap : Map < string , MarkerTiming [ ] > = new Map ( ) ;
94
114
// Instant markers are on separate lines.
95
115
const instantMarkerTimingsMap : Map < string , MarkerTiming > = new Map ( ) ;
116
+ const stackBasedMarkerTimings : MarkerTiming [ ] = [ ] ;
96
117
97
118
// Go through all of the markers.
98
119
for ( const markerIndex of markerIndexes ) {
@@ -109,48 +130,60 @@ export function getMarkerTiming(
109
130
markerTiming . length ++ ;
110
131
} ;
111
132
112
- const bucketName = categories ? categories [ marker . category ] . name : 'None' ;
133
+ const schema = markerSchemaByName
134
+ ? getSchemaFromMarker ( markerSchemaByName , marker . name , marker . data )
135
+ : null ;
136
+ let isStackBased = schema !== null && schema . isStackBased === true ;
137
+ if ( marker . end === null ) {
138
+ // XXXmstange let's see how we like this
139
+ isStackBased = true ;
140
+ }
141
+
142
+ // eslint-disable-next-line no-nested-ternary
143
+ const bucketName = isStackBased
144
+ ? 'Stack'
145
+ : categories
146
+ ? categories [ marker . category ] . name
147
+ : 'None' ;
113
148
114
149
// We want to group all network requests in the same line. Indeed they all
115
150
// have different names and they'd end up with one single request in each
116
151
// line without this special handling.
117
- const markerLineName =
118
- marker . data && marker . data . type === 'Network'
152
+ // eslint-disable-next-line no-nested-ternary
153
+ const markerLineName = isStackBased
154
+ ? 'Stack'
155
+ : marker . data && marker . data . type === 'Network'
119
156
? 'Network Requests'
120
157
: marker . name ;
121
158
122
- const emptyTiming = ( { instantOnly } ) : MarkerTiming => ( {
123
- start : [ ] ,
124
- end : [ ] ,
125
- index : [ ] ,
126
- name : markerLineName ,
127
- bucket : bucketName ,
128
- instantOnly,
129
- length : 0 ,
130
- } ) ;
131
-
132
- if ( marker . end === null ) {
159
+ if ( marker . end === null && ! isStackBased ) {
133
160
// This is an instant marker.
134
161
let instantMarkerTiming = instantMarkerTimingsMap . get ( markerLineName ) ;
135
162
if ( ! instantMarkerTiming ) {
136
- instantMarkerTiming = emptyTiming ( { instantOnly : true } ) ;
163
+ instantMarkerTiming = _createEmptyTiming (
164
+ markerLineName ,
165
+ bucketName ,
166
+ true
167
+ ) ;
137
168
instantMarkerTimingsMap . set ( markerLineName , instantMarkerTiming ) ;
138
169
}
139
170
addCurrentMarkerToMarkerTiming ( instantMarkerTiming ) ;
140
171
continue ;
141
172
}
142
173
143
174
// This is an interval marker.
144
- let markerTimingsForName = intervalMarkerTimingsMap . get ( markerLineName ) ;
145
- if ( markerTimingsForName === undefined ) {
146
- markerTimingsForName = [ ] ;
147
- intervalMarkerTimingsMap . set ( markerLineName , markerTimingsForName ) ;
175
+ let timingRows = isStackBased
176
+ ? stackBasedMarkerTimings
177
+ : intervalMarkerTimingsMap . get ( markerLineName ) ;
178
+ if ( timingRows === undefined ) {
179
+ timingRows = [ ] ;
180
+ intervalMarkerTimingsMap . set ( markerLineName , timingRows ) ;
148
181
}
149
182
150
183
// Find the first row where the new marker fits.
151
184
// Since the markers are sorted, look at the last added marker in this row. If
152
185
// the new marker fits, go ahead and insert it.
153
- const foundMarkerTiming = markerTimingsForName . find (
186
+ const foundMarkerTiming = timingRows . find (
154
187
( markerTiming ) =>
155
188
markerTiming . end [ markerTiming . length - 1 ] <= marker . start
156
189
) ;
@@ -160,29 +193,35 @@ export function getMarkerTiming(
160
193
continue ;
161
194
}
162
195
163
- if ( markerTimingsForName . length >= MAX_STACKING_DEPTH ) {
196
+ if ( timingRows . length >= MAX_STACKING_DEPTH ) {
164
197
// There are too many markers stacked around the same time already, let's
165
198
// ignore this marker.
166
199
continue ;
167
200
}
168
201
169
202
// Otherwise, let's add a new row!
170
- const newTiming = emptyTiming ( { instantOnly : false } ) ;
203
+ const newTiming = _createEmptyTiming ( markerLineName , bucketName , false ) ;
171
204
addCurrentMarkerToMarkerTiming ( newTiming ) ;
172
- markerTimingsForName . push ( newTiming ) ;
205
+ timingRows . push ( newTiming ) ;
173
206
continue ;
174
207
}
175
208
176
209
// Flatten out the maps into a single array.
177
210
// One item in this array is one line in the drawn canvas.
178
- const allMarkerTimings = [ ...instantMarkerTimingsMap . values ( ) ] . concat (
179
- ... intervalMarkerTimingsMap . values ( )
180
- ) ;
211
+ const allMarkerTimings = [ ...instantMarkerTimingsMap . values ( ) ]
212
+ . concat ( ... intervalMarkerTimingsMap . values ( ) )
213
+ . concat ( ... stackBasedMarkerTimings ) ;
181
214
182
215
// Sort all the marker timings in place, first by the bucket, then by their names.
183
216
allMarkerTimings . sort ( ( a , b ) => {
184
217
if ( a . bucket !== b . bucket ) {
185
218
// Sort by buckets first.
219
+ if ( a . bucket === 'Stack' ) {
220
+ return - 1 ;
221
+ }
222
+ if ( b . bucket === 'Stack' ) {
223
+ return 1 ;
224
+ }
186
225
// Show the 'Test' category first. Test markers are almost guaranteed to
187
226
// be the most relevant when they exist.
188
227
if ( a . bucket === 'Test' ) {
@@ -286,12 +325,14 @@ export function getMarkerTimingAndBuckets(
286
325
markerIndexes : MarkerIndex [ ] ,
287
326
// Categories can be null for things like Network Markers, where we don't care to
288
327
// break things up by category.
289
- categories : ?CategoryList
328
+ categories : ?CategoryList ,
329
+ markerSchemaByName : ?MarkerSchemaByName
290
330
) : MarkerTimingAndBuckets {
291
331
const allMarkerTimings = getMarkerTiming (
292
332
getMarker ,
293
333
markerIndexes ,
294
- categories
334
+ categories ,
335
+ markerSchemaByName
295
336
) ;
296
337
297
338
// Interleave the bucket names in between the marker timings.
0 commit comments