OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <!-- | 2 <!-- |
3 Copyright (c) 2015 The Chromium Authors. All rights reserved. | 3 Copyright (c) 2015 The Chromium Authors. All rights reserved. |
4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
5 found in the LICENSE file. | 5 found in the LICENSE file. |
6 --> | 6 --> |
7 | 7 |
8 <link rel="import" href="/tracing/base/range.html"> | 8 <link rel="import" href="/tracing/base/range.html"> |
9 <link rel="import" href="/tracing/base/task.html"> | 9 <link rel="import" href="/tracing/base/task.html"> |
10 <link rel="import" href="/tracing/model/event_set.html"> | 10 <link rel="import" href="/tracing/model/event_set.html"> |
(...skipping 13 matching lines...) Expand all Loading... |
24 flex: 1 1 auto; | 24 flex: 1 1 auto; |
25 align-self: stretch; | 25 align-self: stretch; |
26 } | 26 } |
27 </style> | 27 </style> |
28 <tr-ui-b-table id="table"></tr-ui-b-table> | 28 <tr-ui-b-table id="table"></tr-ui-b-table> |
29 </template> | 29 </template> |
30 </dom-module> | 30 </dom-module> |
31 <script> | 31 <script> |
32 'use strict'; | 32 'use strict'; |
33 | 33 |
| 34 function* getEventInFlowEvents(event) { |
| 35 if (!event.inFlowEvents) |
| 36 return; |
| 37 yield * event.inFlowEvents; |
| 38 } |
| 39 |
| 40 function* getEventOutFlowEvents(event) { |
| 41 if (!event.outFlowEvents) |
| 42 return; |
| 43 yield * event.outFlowEvents; |
| 44 } |
| 45 |
| 46 function* getEventAncestors(event) { |
| 47 if (!event.enumerateAllAncestors) |
| 48 return; |
| 49 yield * event.enumerateAllAncestors(); |
| 50 } |
| 51 |
| 52 function* getEventDescendents(event) { |
| 53 if (!event.enumerateAllDescendents) |
| 54 return; |
| 55 yield * event.enumerateAllDescendents(); |
| 56 } |
| 57 |
34 Polymer({ | 58 Polymer({ |
35 is: 'tr-ui-a-related-events', | 59 is: 'tr-ui-a-related-events', |
36 | 60 |
37 ready: function() { | 61 ready: function() { |
38 this.eventGroups_ = []; | 62 this.eventGroups_ = []; |
39 this.cancelFunctions_ = []; | 63 this.cancelFunctions_ = []; |
40 | 64 |
41 this.$.table.tableColumns = [ | 65 this.$.table.tableColumns = [ |
42 { | 66 { |
43 title: 'Event(s)', | 67 title: 'Event(s)', |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 }); | 141 }); |
118 this.cancelFunctions_ = []; | 142 this.cancelFunctions_ = []; |
119 }, | 143 }, |
120 | 144 |
121 addConnectedEvents_: function(eventSet) { | 145 addConnectedEvents_: function(eventSet) { |
122 this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( | 146 this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( |
123 'Preceding events', | 147 'Preceding events', |
124 'Add all events that have led to the selected one(s), connected by ' + | 148 'Add all events that have led to the selected one(s), connected by ' + |
125 'flow arrows or by call stack.', | 149 'flow arrows or by call stack.', |
126 eventSet, | 150 eventSet, |
127 function(event, events) { | 151 function*(event) { |
128 this.addInFlowEvents_(event, events); | 152 yield * getEventInFlowEvents(event); |
129 this.addAncestors_(event, events); | 153 yield * getEventAncestors(event); |
130 if (event.startSlice) | 154 if (event.startSlice) |
131 events.push(event.startSlice); | 155 yield event.startSlice; |
132 }.bind(this))); | 156 }.bind(this))); |
133 this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( | 157 this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( |
134 'Following events', | 158 'Following events', |
135 'Add all events that have been caused by the selected one(s), ' + | 159 'Add all events that have been caused by the selected one(s), ' + |
136 'connected by flow arrows or by call stack.', | 160 'connected by flow arrows or by call stack.', |
137 eventSet, | 161 eventSet, |
138 function(event, events) { | 162 function*(event) { |
139 this.addOutFlowEvents_(event, events); | 163 yield * getEventOutFlowEvents(event); |
140 this.addDescendents_(event, events); | 164 yield * getEventDescendents(event); |
141 if (event.endSlice) | 165 if (event.endSlice) |
142 events.push(event.endSlice); | 166 yield event.endSlice; |
143 }.bind(this))); | 167 }.bind(this))); |
144 this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( | 168 this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( |
145 'All connected events', | 169 'All connected events', |
146 'Add all events connected to the selected one(s) by flow arrows or ' + | 170 'Add all events connected to the selected one(s) by flow arrows or ' + |
147 'by call stack.', | 171 'by call stack.', |
148 eventSet, | 172 eventSet, |
149 function(event, events) { | 173 function*(event) { |
150 this.addInFlowEvents_(event, events); | 174 yield * getEventInFlowEvents(event); |
151 this.addOutFlowEvents_(event, events); | 175 yield * getEventOutFlowEvents(event); |
152 this.addAncestors_(event, events); | 176 yield * getEventAncestors(event); |
153 this.addDescendents_(event, events); | 177 yield * getEventDescendents(event); |
154 if (event.startSlice) | 178 if (event.startSlice) |
155 events.push(event.startSlice); | 179 yield event.startSlice; |
156 if (event.endSlice) | 180 if (event.endSlice) |
157 events.push(event.endSlice); | 181 yield event.endSlice; |
158 }.bind(this))); | 182 }.bind(this))); |
159 }, | 183 }, |
160 | 184 |
161 createEventsLinkIfNeeded_: function(title, tooltip, events, addFunction) { | 185 createEventsLinkIfNeeded_: function(title, tooltip, events, connectedFn) { |
162 events = new tr.model.EventSet(events); | 186 events = new tr.model.EventSet(events); |
163 var lengthBefore = events.length; | 187 var eventsToProcess = new Set(events); |
| 188 // for (var event of events) |
| 189 // eventsToProcess.add(event); |
| 190 var wasChanged = false; |
164 var task; | 191 var task; |
165 var isCanceled = false; | 192 var isCanceled = false; |
166 function addEventsUntilTimeout(startingIndex) { | 193 function addEventsUntilTimeout() { |
167 if (isCanceled) | 194 if (isCanceled) |
168 return; | 195 return; |
169 var startingTime = window.performance.now(); | 196 // Let's grant ourselves a budget of 8 ms. If time runs out, then |
170 while (startingIndex < events.length) { | 197 // create another task to do the rest. |
171 addFunction(events[startingIndex], events); | 198 var timeout = window.performance.now() + 8; |
172 startingIndex++; | 199 // TODO(alexandermont): Don't check window.performance.now |
173 // Let's grant ourselves a budget of 8ms. | 200 // every iteration. |
174 if (window.performance.now() - startingTime > 8) { | 201 while (eventsToProcess.size > 0 && |
| 202 window.performance.now() <= timeout) { |
| 203 // Get the next event. |
| 204 var nextEvent = tr.b.getFirstElement(eventsToProcess); |
| 205 eventsToProcess.delete(nextEvent); |
| 206 |
| 207 // Add the connected events to the list. |
| 208 for (var eventToAdd of connectedFn(nextEvent)) { |
| 209 if (!events.contains(eventToAdd)) { |
| 210 events.push(eventToAdd); |
| 211 eventsToProcess.add(eventToAdd); |
| 212 wasChanged = true; |
| 213 } |
| 214 } |
| 215 } |
| 216 if (eventsToProcess.size > 0) { |
| 217 // There are still events to process, but we ran out of time. Post |
| 218 // more work for later. |
175 var newTask = new tr.b.Task( | 219 var newTask = new tr.b.Task( |
176 addEventsUntilTimeout.bind(this, startingIndex), this); | 220 addEventsUntilTimeout.bind(this), this); |
177 task.after(newTask); | 221 task.after(newTask); |
178 task = newTask; | 222 task = newTask; |
179 return; | 223 return; |
180 } | |
181 } | 224 } |
182 // Went through all events, add the link. | 225 // Went through all events, add the link. |
183 if (lengthBefore === events.length) | 226 if (!wasChanged) |
184 return; | 227 return; |
185 this.eventGroups_.push({ | 228 this.eventGroups_.push({ |
186 type: title, | 229 type: title, |
187 tooltip: tooltip, | 230 tooltip: tooltip, |
188 selection: events | 231 selection: events |
189 }); | 232 }); |
190 this.updateContents_(); | 233 this.updateContents_(); |
191 }; | 234 }; |
192 function cancelTask() { | 235 function cancelTask() { |
193 isCanceled = true; | 236 isCanceled = true; |
194 } | 237 } |
195 task = new tr.b.Task(addEventsUntilTimeout.bind(this, 0), this); | 238 task = new tr.b.Task(addEventsUntilTimeout.bind(this), this); |
196 tr.b.Task.RunWhenIdle(task); | 239 tr.b.Task.RunWhenIdle(task); |
197 return cancelTask; | 240 return cancelTask; |
198 }, | 241 }, |
199 | 242 |
200 addInFlowEvents_: function(event, eventSet) { | 243 addOverlappingSamples_: function(eventSet) { |
201 if (!event.inFlowEvents) | 244 var samples = new tr.model.EventSet; |
202 return; | 245 for (var slice of eventSet) { |
203 event.inFlowEvents.forEach(function(e) { | 246 if (!slice.parentContainer || !slice.parentContainer.samples) |
204 eventSet.push(e); | 247 continue; |
205 }); | 248 var candidates = slice.parentContainer.samples; |
206 }, | 249 var range = tr.b.Range.fromExplicitRange( |
207 | 250 slice.start, slice.start + slice.duration); |
208 addOutFlowEvents_: function(event, eventSet) { | 251 var filteredSamples = range.filterArray( |
209 if (!event.outFlowEvents) | 252 candidates, function(value) {return value.start;}); |
210 return; | 253 for (var sample of filteredSamples) |
211 event.outFlowEvents.forEach(function(e) { | 254 samples.push(sample); |
212 eventSet.push(e); | 255 } |
213 }); | 256 if (samples.length > 0) { |
214 }, | 257 this.eventGroups_.push({ |
215 | 258 type: 'Overlapping samples', |
216 addAncestors_: function(event, eventSet) { | 259 tooltip: 'All samples overlapping the selected slice(s).', |
217 if (!event.iterateAllAncestors) | 260 selection: samples |
218 return; | 261 }); |
219 event.iterateAllAncestors(function(e) { | 262 } |
220 eventSet.push(e); | |
221 }); | |
222 }, | |
223 | |
224 addDescendents_: function(event, eventSet) { | |
225 if (!event.iterateAllDescendents) | |
226 return; | |
227 event.iterateAllDescendents(function(e) { | |
228 eventSet.push(e); | |
229 }); | |
230 }, | 263 }, |
231 | 264 |
232 addOverlappingSamples_: function(eventSet) { | 265 addOverlappingSamples_: function(eventSet) { |
233 var samples = new tr.model.EventSet; | 266 var samples = new tr.model.EventSet; |
234 eventSet.forEach(function(slice) { | 267 eventSet.forEach(function(slice) { |
235 if (!slice.parentContainer || !slice.parentContainer.samples) | 268 if (!slice.parentContainer || !slice.parentContainer.samples) |
236 return; | 269 return; |
237 var candidates = slice.parentContainer.samples; | 270 var candidates = slice.parentContainer.samples; |
238 var range = tr.b.Range.fromExplicitRange( | 271 var range = tr.b.Range.fromExplicitRange( |
239 slice.start, slice.start + slice.duration); | 272 slice.start, slice.start + slice.duration); |
(...skipping 15 matching lines...) Expand all Loading... |
255 updateContents_: function() { | 288 updateContents_: function() { |
256 var table = this.$.table; | 289 var table = this.$.table; |
257 if (this.eventGroups_ === undefined) | 290 if (this.eventGroups_ === undefined) |
258 table.tableRows = []; | 291 table.tableRows = []; |
259 else | 292 else |
260 table.tableRows = this.eventGroups_.slice(); | 293 table.tableRows = this.eventGroups_.slice(); |
261 table.rebuild(); | 294 table.rebuild(); |
262 } | 295 } |
263 }); | 296 }); |
264 </script> | 297 </script> |
OLD | NEW |