Index: chrome/browser/resources/gpu_internals/timeline_model.js |
diff --git a/chrome/browser/resources/gpu_internals/timeline_model.js b/chrome/browser/resources/gpu_internals/timeline_model.js |
index 1739e3c195685dc44f5c6434c218a9145a2c5774..c40ab71493f4d3e8c63104712600e924c2839d50 100644 |
--- a/chrome/browser/resources/gpu_internals/timeline_model.js |
+++ b/chrome/browser/resources/gpu_internals/timeline_model.js |
@@ -65,6 +65,11 @@ cr.define('gpu', function() { |
} |
TimelineThread.prototype = { |
+ /** |
+ * Name of the thread, if present. |
+ */ |
+ name: undefined, |
+ |
getSubrow: function(i) { |
while (i >= this.subRows.length) |
this.subRows.push([]); |
@@ -83,11 +88,26 @@ cr.define('gpu', function() { |
this.nonNestedSubRows.push([slice]); |
}, |
+ /** |
+ * Updates the minTimestamp and maxTimestamp fields based on the |
+ * current slices and nonNestedSubRows attached to the thread. |
+ */ |
updateBounds: function() { |
- var slices = this.subRows[0]; |
- if (slices.length != 0) { |
- this.minTimestamp = slices[0].start; |
- this.maxTimestamp = slices[slices.length - 1].end; |
+ var values = []; |
+ var slices; |
+ if (this.subRows[0].length != 0) { |
+ slices = this.subRows[0]; |
+ values.push(slices[0].start); |
+ values.push(slices[slices.length - 1].end); |
+ } |
+ for (var i = 0; i < this.nonNestedSubRows.length; ++i) { |
+ slices = this.nonNestedSubRows[i]; |
+ values.push(slices[0].start); |
+ values.push(slices[slices.length - 1].end); |
+ } |
+ if (values.length) { |
+ this.minTimestamp = Math.min.apply(Math, values); |
+ this.maxTimestamp = Math.max.apply(Math, values); |
} else { |
this.minTimestamp = undefined; |
this.maxTimestamp = undefined; |
@@ -97,6 +117,30 @@ cr.define('gpu', function() { |
}; |
/** |
+ * Comparison between threads that orders first by pid, |
+ * then by names, then by tid. |
+ */ |
+ TimelineThread.compare = function(x,y) { |
+ if(x.parent.pid != y.parent.pid) { |
+ return x.parent.pid - y.parent.pid; |
+ } |
+ |
+ if (x.name && y.name) { |
+ var tmp = x.name.localeCompare(y.name); |
+ if (tmp == 0) |
+ return x.tid - y.tid; |
+ return tmp; |
+ } else if (x.name) { |
+ return -1; |
+ } else if (y.name){ |
+ return 1; |
+ } else { |
+ return x.tid - y.tid; |
+ } |
+ }; |
+ |
+ |
+ /** |
* The TimelineProcess represents a single process in the |
* trace. Right now, we keep this around purely for bookkeeping |
* reasons. |
@@ -123,6 +167,7 @@ cr.define('gpu', function() { |
*/ |
function TimelineModel(events) { |
this.processes = {}; |
+ this.importErrors = []; |
if (events) |
this.importEvents(events); |
@@ -144,7 +189,7 @@ cr.define('gpu', function() { |
importEvents: function(events) { |
// A ptid is a pid and tid joined together x:y fashion, eg 1024:130 |
// The ptid is a unique key for a thread in the trace. |
- |
+ this.importErrors = []; |
// Threadstate |
const numColorIds = 30; |
@@ -188,7 +233,7 @@ cr.define('gpu', function() { |
sliceID += ';' + event.args[x]; |
} |
if (state.openNonNestedSlices[sliceID]) |
- console.log('Event ' + sliceID + ' already open.'); |
+ this.importErrors.push('Event ' + sliceID + ' already open.'); |
state.openNonNestedSlices[sliceID] = slice; |
} else |
state.openSlices.push(slice); |
@@ -229,12 +274,19 @@ cr.define('gpu', function() { |
} else if (event.ph == 'I') { |
// TODO(nduca): Implement parsing of immediate events. |
console.log('Parsing of I-type events not implemented.'); |
+ } else if (event.ph == 'M') { |
+ if (event.name == 'thread_name') { |
+ var thread = this.getProcess(event.pid).getThread(event.tid); |
+ thread.name = event.args.name; |
+ } else { |
+ this.importErrors.push('Unrecognized metadata name: ' + event.name); |
+ } |
} else { |
- throw new Error('Unrecognized event phase: ' + event.ph + |
+ this.importErrors.push('Unrecognized event phase: ' + event.ph + |
'(' + event.name + ')'); |
} |
} |
- |
+ this.pruneEmptyThreads(); |
this.updateBounds(); |
// Add end events for any events that are still on the stack. These |
@@ -268,6 +320,22 @@ cr.define('gpu', function() { |
this.maxTimestamp = this.maxTimestamp + boost; |
}, |
+ /** |
+ * Removes threads from the model that have no subrows. |
+ */ |
+ pruneEmptyThreads: function() { |
+ for (var pid in this.processes) { |
+ var process = this.processes[pid]; |
+ var prunedThreads = []; |
+ for (var tid in process.threads) { |
+ var thread = process.threads[tid]; |
+ if (thread.subRows[0].length || thread.nonNestedSubRows.legnth) |
+ prunedThreads.push(thread); |
+ } |
+ process.threads = prunedThreads; |
+ } |
+ }, |
+ |
updateBounds: function() { |
var wmin = Infinity; |
var wmax = -wmin; |
@@ -275,7 +343,8 @@ cr.define('gpu', function() { |
for (var tI = 0; tI < threads.length; tI++) { |
var thread = threads[tI]; |
thread.updateBounds(); |
- if (thread.minTimestamp && thread.maxTimestamp) { |
+ if (thread.minTimestamp != undefined && |
+ thread.maxTimestamp != undefined) { |
wmin = Math.min(wmin, thread.minTimestamp); |
wmax = Math.max(wmax, thread.maxTimestamp); |
} |