summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-18 22:12:18 +0000
committerjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-18 22:12:18 +0000
commitc3f3840beeeba4bdead501e8ded1df7177eaa8af (patch)
treeff7eef3d1bdab4b7a64309772ebb30b5078bd288
parent6b15434bf59bad3c5fe1f632adcc49746b23aaed (diff)
downloadchromium_src-c3f3840beeeba4bdead501e8ded1df7177eaa8af.zip
chromium_src-c3f3840beeeba4bdead501e8ded1df7177eaa8af.tar.gz
chromium_src-c3f3840beeeba4bdead501e8ded1df7177eaa8af.tar.bz2
Add support for non-nested trace events.
Trace events that start with "*" are treated as non-nested, so opening and closing events are matched by name and args, not with a stack. They're also displayed in a separate set of subrows apart from normal events. This allows for long-running processes that occur during several function calls to be displayed. Some events to track GPU process throttling have also been added using this mechanism. BUG=79800 TEST= Review URL: http://codereview.chromium.org/6873003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85824 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/resources/gpu_internals/timeline_model.js85
-rw-r--r--chrome/browser/resources/gpu_internals/timeline_track.js31
-rw-r--r--chrome/browser/resources/gpu_internals/tracing_controller_tests.js16
3 files changed, 100 insertions, 32 deletions
diff --git a/chrome/browser/resources/gpu_internals/timeline_model.js b/chrome/browser/resources/gpu_internals/timeline_model.js
index 848308d..0cb9b90 100644
--- a/chrome/browser/resources/gpu_internals/timeline_model.js
+++ b/chrome/browser/resources/gpu_internals/timeline_model.js
@@ -51,7 +51,8 @@ cr.define('gpu', function() {
/**
* A TimelineThread stores all the trace events collected for a particular
* thread. We organize the slices on a thread by "subrows," where subrow 0
- * has all the root slices, subrow 1 those nested 1 deep, and so on.
+ * has all the root slices, subrow 1 those nested 1 deep, and so on. There
+ * is also a set of non-nested subrows.
*
* @constructor
*/
@@ -59,6 +60,7 @@ cr.define('gpu', function() {
this.parent = parent;
this.tid = tid;
this.subRows = [[]];
+ this.nonNestedSubRows = [];
}
TimelineThread.prototype = {
@@ -68,6 +70,18 @@ cr.define('gpu', function() {
return this.subRows[i];
},
+ addNonNestedSlice: function(slice) {
+ for (var i = 0; i < this.nonNestedSubRows.length; i++) {
+ var currSubRow = this.nonNestedSubRows[i];
+ var lastSlice = currSubRow[currSubRow.length - 1];
+ if (slice.start >= lastSlice.start + lastSlice.duration) {
+ currSubRow.push(slice);
+ return;
+ }
+ }
+ this.nonNestedSubRows.push([slice]);
+ },
+
updateBounds: function() {
var slices = this.subRows[0];
if (slices.length != 0) {
@@ -135,6 +149,7 @@ cr.define('gpu', function() {
const numColorIds = 12;
function ThreadState(tid) {
this.openSlices = [];
+ this.openNonNestedSlices = {};
}
var threadStateByPTID = {};
@@ -163,24 +178,49 @@ cr.define('gpu', function() {
var colorId = getColor(event.name);
var slice = new TimelineSlice(event.name, colorId, event.ts,
event.args);
- state.openSlices.push(slice);
+ if (event.args['ui-nest'] === '0') {
+ var sliceID = event.name;
+ for (var x in event.args) {
+ sliceID += ';' + event.args[x];
+ }
+ if (state.openNonNestedSlices[sliceID])
+ console.log('Event ' + sliceID + ' already open.');
+ state.openNonNestedSlices[sliceID] = slice;
+ } else
+ state.openSlices.push(slice);
} else if (event.ph == 'E') {
- if (state.openSlices.length == 0) {
- // Ignore E events that that are unmatched.
- continue;
- }
- var slice = state.openSlices.pop();
- slice.duration = event.ts - slice.start;
-
- // Store the slice on the right subrow.
- var thread = this.getProcess(event.pid).getThread(event.tid);
- var subRowIndex = state.openSlices.length;
- thread.getSubrow(subRowIndex).push(slice);
-
- // Add the slice to the subSlices array of its parent.
- if (state.openSlices.length) {
- var parentSlice = state.openSlices[state.openSlices.length - 1];
- parentSlice.subSlices.push(slice);
+ if (event.args['ui-nest'] === '0') {
+ var sliceID = event.name;
+ for (var x in event.args) {
+ sliceID += ';' + event.args[x];
+ }
+ var slice = state.openNonNestedSlices[sliceID];
+ if (!slice)
+ continue;
+ slice.duration = event.ts - slice.start;
+
+ // Store the slice in a non-nested subrow.
+ var thread = this.getProcess(event.pid).getThread(event.tid);
+ thread.addNonNestedSlice(slice);
+ delete state.openNonNestedSlices[name];
+ } else {
+ if (state.openSlices.length == 0) {
+ // Ignore E events that that are unmatched.
+ continue;
+ }
+ var slice = state.openSlices.pop();
+ slice.duration = event.ts - slice.start;
+
+ // Store the slice on the right subrow.
+ var thread = this.getProcess(event.pid).getThread(event.tid);
+ var subRowIndex = state.openSlices.length;
+ thread.getSubrow(subRowIndex).push(slice);
+
+ // Add the slice to the subSlices array of its parent.
+ if (state.openSlices.length) {
+ var parentSlice = state.openSlices[state.openSlices.length - 1];
+ parentSlice.subSlices.push(slice);
+ }
}
} else if (event.ph == 'I') {
// TODO(nduca): Implement parsing of immediate events.
@@ -218,13 +258,18 @@ cr.define('gpu', function() {
var threads = this.getAllThreads();
for (var tI = 0; tI < threads.length; tI++) {
var thread = threads[tI];
- for (var tSR = 0; tSR < thread.subRows.length; tSR++) {
- var subRow = thread.subRows[tSR];
+ var shiftSubRow = function(subRow) {
for (var tS = 0; tS < subRow.length; tS++) {
var slice = subRow[tS];
slice.start = (slice.start - timeBase) / 1000;
slice.duration /= 1000;
}
+ };
+ for (var tSR = 0; tSR < thread.subRows.length; tSR++) {
+ shiftSubRow(thread.subRows[tSR]);
+ }
+ for (var tSR = 0; tSR < thread.nonNestedSubRows.length; tSR++) {
+ shiftSubRow(thread.nonNestedSubRows[tSR]);
}
}
diff --git a/chrome/browser/resources/gpu_internals/timeline_track.js b/chrome/browser/resources/gpu_internals/timeline_track.js
index 2c86967..fe582e0 100644
--- a/chrome/browser/resources/gpu_internals/timeline_track.js
+++ b/chrome/browser/resources/gpu_internals/timeline_track.js
@@ -48,6 +48,17 @@ cr.define('gpu', function() {
return w;
}
+ function addTrack(thisTrack, slices) {
+ var track = new TimelineSliceTrack();
+
+ track.heading = '';
+ track.slices = slices;
+ track.viewport = thisTrack.viewport_;
+
+ thisTrack.tracks_.push(track);
+ thisTrack.appendChild(track);
+ }
+
/**
* Generic base class for timeline tracks
*/
@@ -96,19 +107,15 @@ cr.define('gpu', function() {
this.textContent = '';
this.tracks_ = [];
if (this.thread_) {
+ for (var srI = 0; srI < this.thread_.nonNestedSubRows.length; ++srI) {
+ addTrack(this, this.thread_.nonNestedSubRows[srI]);
+ }
for (var srI = 0; srI < this.thread_.subRows.length; ++srI) {
- var track = new TimelineSliceTrack();
-
- if (srI == 0)
- track.heading = this.thread_.parent.pid + ': ' +
- this.thread_.tid + ': ';
- else
- track.heading = '';
- track.slices = this.thread_.subRows[srI];
- track.viewport = this.viewport_;
-
- this.tracks_.push(track);
- this.appendChild(track);
+ addTrack(this, this.thread_.subRows[srI]);
+ }
+ if (this.tracks_.length > 0) {
+ this.tracks_[0].heading = this.thread_.parent.pid + ': ' +
+ this.thread_.tid + ': ';
}
}
},
diff --git a/chrome/browser/resources/gpu_internals/tracing_controller_tests.js b/chrome/browser/resources/gpu_internals/tracing_controller_tests.js
index 000f89b..a331b9b 100644
--- a/chrome/browser/resources/gpu_internals/tracing_controller_tests.js
+++ b/chrome/browser/resources/gpu_internals/tracing_controller_tests.js
@@ -28,6 +28,22 @@ var allTracingControllerTestDataSets;
{"cat":"PERF","pid":22630,"tid":22631,"ts":827,"ph":"B","name":"A","args":{}},
{"cat":"PERF","pid":22630,"tid":22631,"ts":854,"ph":"E","name":"A","args":{}}
]
+ },
+ {
+ name: "nonnested_trace",
+ events: [
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':826,'ph':'B','name':'A','args':{}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':827,'ph':'B','name':'Asub','args':{}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':829,'ph':'B','name':'NonNest','args':{'id':'1','ui-nest':'0'}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':830,'ph':'B','name':'NonNest','args':{'id':'2','ui-nest':'0'}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':831,'ph':'E','name':'Asub','args':{}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':832,'ph':'E','name':'NonNest','args':{'id':'1','ui-nest':'0'}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':833,'ph':'E','name':'NonNest','args':{'id':'2','ui-nest':'0'}},
+ {'cat':'PERF','pid':22630,'tid':22630,'ts':834,'ph':'E','name':'A','args':{}},
+
+ {'cat':'PERF','pid':22630,'tid':22631,'ts':827,'ph':'B','name':'A','args':{}},
+ {'cat':'PERF','pid':22630,'tid':22631,'ts':854,'ph':'E','name':'A','args':{}}
+ ]
}
];
allTracingControllerTestDataSets = dataSets;