Index: tracing/tracing/ui/analysis/related_events.html |
diff --git a/tracing/tracing/ui/analysis/related_events.html b/tracing/tracing/ui/analysis/related_events.html |
index 90cbdfd118ee0bdd6a5f0b983736d2855a5f86fa..46a3c24fb776a3406177e9b9125c032f6d36a53c 100644 |
--- a/tracing/tracing/ui/analysis/related_events.html |
+++ b/tracing/tracing/ui/analysis/related_events.html |
@@ -31,6 +31,30 @@ found in the LICENSE file. |
<script> |
'use strict'; |
+function* getEventInFlowEvents(event) { |
+ if (!event.inFlowEvents) |
+ return; |
+ yield * event.inFlowEvents; |
+} |
+ |
+function* getEventOutFlowEvents(event) { |
+ if (!event.outFlowEvents) |
+ return; |
+ yield * event.outFlowEvents; |
+} |
+ |
+function* getEventAncestors(event) { |
+ if (!event.enumerateAllAncestors) |
+ return; |
+ yield * event.enumerateAllAncestors(); |
+} |
+ |
+function* getEventDescendents(event) { |
+ if (!event.enumerateAllDescendents) |
+ return; |
+ yield * event.enumerateAllDescendents(); |
+} |
+ |
Polymer({ |
is: 'tr-ui-a-related-events', |
@@ -124,63 +148,82 @@ Polymer({ |
'Add all events that have led to the selected one(s), connected by ' + |
'flow arrows or by call stack.', |
eventSet, |
- function(event, events) { |
- this.addInFlowEvents_(event, events); |
- this.addAncestors_(event, events); |
+ function*(event) { |
+ yield * getEventInFlowEvents(event); |
+ yield * getEventAncestors(event); |
if (event.startSlice) |
- events.push(event.startSlice); |
+ yield event.startSlice; |
}.bind(this))); |
this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( |
'Following events', |
'Add all events that have been caused by the selected one(s), ' + |
'connected by flow arrows or by call stack.', |
eventSet, |
- function(event, events) { |
- this.addOutFlowEvents_(event, events); |
- this.addDescendents_(event, events); |
+ function*(event) { |
+ yield * getEventOutFlowEvents(event); |
+ yield * getEventDescendents(event); |
if (event.endSlice) |
- events.push(event.endSlice); |
+ yield event.endSlice; |
}.bind(this))); |
this.cancelFunctions_.push(this.createEventsLinkIfNeeded_( |
'All connected events', |
'Add all events connected to the selected one(s) by flow arrows or ' + |
'by call stack.', |
eventSet, |
- function(event, events) { |
- this.addInFlowEvents_(event, events); |
- this.addOutFlowEvents_(event, events); |
- this.addAncestors_(event, events); |
- this.addDescendents_(event, events); |
+ function*(event) { |
+ yield * getEventInFlowEvents(event); |
+ yield * getEventOutFlowEvents(event); |
+ yield * getEventAncestors(event); |
+ yield * getEventDescendents(event); |
if (event.startSlice) |
- events.push(event.startSlice); |
+ yield event.startSlice; |
if (event.endSlice) |
- events.push(event.endSlice); |
+ yield event.endSlice; |
}.bind(this))); |
}, |
- createEventsLinkIfNeeded_: function(title, tooltip, events, addFunction) { |
+ createEventsLinkIfNeeded_: function(title, tooltip, events, connectedFn) { |
events = new tr.model.EventSet(events); |
- var lengthBefore = events.length; |
+ var eventsToProcess = new Set(events); |
+ // for (var event of events) |
+ // eventsToProcess.add(event); |
+ var wasChanged = false; |
var task; |
var isCanceled = false; |
- function addEventsUntilTimeout(startingIndex) { |
+ function addEventsUntilTimeout() { |
if (isCanceled) |
return; |
- var startingTime = window.performance.now(); |
- while (startingIndex < events.length) { |
- addFunction(events[startingIndex], events); |
- startingIndex++; |
- // Let's grant ourselves a budget of 8ms. |
- if (window.performance.now() - startingTime > 8) { |
+ // Let's grant ourselves a budget of 8 ms. If time runs out, then |
+ // create another task to do the rest. |
+ var timeout = window.performance.now() + 8; |
+ // TODO(alexandermont): Don't check window.performance.now |
+ // every iteration. |
+ while (eventsToProcess.size > 0 && |
+ window.performance.now() <= timeout) { |
+ // Get the next event. |
+ var nextEvent = tr.b.getFirstElement(eventsToProcess); |
+ eventsToProcess.delete(nextEvent); |
+ |
+ // Add the connected events to the list. |
+ for (var eventToAdd of connectedFn(nextEvent)) { |
+ if (!events.contains(eventToAdd)) { |
+ events.push(eventToAdd); |
+ eventsToProcess.add(eventToAdd); |
+ wasChanged = true; |
+ } |
+ } |
+ } |
+ if (eventsToProcess.size > 0) { |
+ // There are still events to process, but we ran out of time. Post |
+ // more work for later. |
var newTask = new tr.b.Task( |
- addEventsUntilTimeout.bind(this, startingIndex), this); |
+ addEventsUntilTimeout.bind(this), this); |
task.after(newTask); |
task = newTask; |
return; |
- } |
} |
// Went through all events, add the link. |
- if (lengthBefore === events.length) |
+ if (!wasChanged) |
return; |
this.eventGroups_.push({ |
type: title, |
@@ -192,41 +235,31 @@ Polymer({ |
function cancelTask() { |
isCanceled = true; |
} |
- task = new tr.b.Task(addEventsUntilTimeout.bind(this, 0), this); |
+ task = new tr.b.Task(addEventsUntilTimeout.bind(this), this); |
tr.b.Task.RunWhenIdle(task); |
return cancelTask; |
}, |
- addInFlowEvents_: function(event, eventSet) { |
- if (!event.inFlowEvents) |
- return; |
- event.inFlowEvents.forEach(function(e) { |
- eventSet.push(e); |
- }); |
- }, |
- |
- addOutFlowEvents_: function(event, eventSet) { |
- if (!event.outFlowEvents) |
- return; |
- event.outFlowEvents.forEach(function(e) { |
- eventSet.push(e); |
- }); |
- }, |
- |
- addAncestors_: function(event, eventSet) { |
- if (!event.iterateAllAncestors) |
- return; |
- event.iterateAllAncestors(function(e) { |
- eventSet.push(e); |
- }); |
- }, |
- |
- addDescendents_: function(event, eventSet) { |
- if (!event.iterateAllDescendents) |
- return; |
- event.iterateAllDescendents(function(e) { |
- eventSet.push(e); |
- }); |
+ addOverlappingSamples_: function(eventSet) { |
+ var samples = new tr.model.EventSet; |
+ for (var slice of eventSet) { |
+ if (!slice.parentContainer || !slice.parentContainer.samples) |
+ continue; |
+ var candidates = slice.parentContainer.samples; |
+ var range = tr.b.Range.fromExplicitRange( |
+ slice.start, slice.start + slice.duration); |
+ var filteredSamples = range.filterArray( |
+ candidates, function(value) {return value.start;}); |
+ for (var sample of filteredSamples) |
+ samples.push(sample); |
+ } |
+ if (samples.length > 0) { |
+ this.eventGroups_.push({ |
+ type: 'Overlapping samples', |
+ tooltip: 'All samples overlapping the selected slice(s).', |
+ selection: samples |
+ }); |
+ } |
}, |
addOverlappingSamples_: function(eventSet) { |