Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: chrome/browser/resources/gpu_internals/timeline_model.js

Issue 7495036: about:gpu support for thread name metadata. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixes based on jhawkins Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 /** 6 /**
7 * @fileoverview TimelineModel is a parsed representation of the 7 * @fileoverview TimelineModel is a parsed representation of the
8 * TraceEvents obtained from base/trace_event in which the begin-end 8 * TraceEvents obtained from base/trace_event in which the begin-end
9 * tokens are converted into a hierarchy of processes, threads, 9 * tokens are converted into a hierarchy of processes, threads,
10 * subrows, and slices. 10 * subrows, and slices.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 * @constructor 58 * @constructor
59 */ 59 */
60 function TimelineThread(parent, tid) { 60 function TimelineThread(parent, tid) {
61 this.parent = parent; 61 this.parent = parent;
62 this.tid = tid; 62 this.tid = tid;
63 this.subRows = [[]]; 63 this.subRows = [[]];
64 this.nonNestedSubRows = []; 64 this.nonNestedSubRows = [];
65 } 65 }
66 66
67 TimelineThread.prototype = { 67 TimelineThread.prototype = {
68 /**
69 * Name of the thread, if present.
70 */
71 name: undefined,
James Hawkins 2011/08/01 18:28:49 Is this intended to be private?
nduca 2011/08/01 20:52:22 Nope, its public. Should I be exposing this via a
James Hawkins 2011/08/01 21:01:24 Hmm, likely though I won't ask you to do that. It'
72
68 getSubrow: function(i) { 73 getSubrow: function(i) {
69 while (i >= this.subRows.length) 74 while (i >= this.subRows.length)
70 this.subRows.push([]); 75 this.subRows.push([]);
71 return this.subRows[i]; 76 return this.subRows[i];
72 }, 77 },
73 78
74 addNonNestedSlice: function(slice) { 79 addNonNestedSlice: function(slice) {
75 for (var i = 0; i < this.nonNestedSubRows.length; i++) { 80 for (var i = 0; i < this.nonNestedSubRows.length; i++) {
76 var currSubRow = this.nonNestedSubRows[i]; 81 var currSubRow = this.nonNestedSubRows[i];
77 var lastSlice = currSubRow[currSubRow.length - 1]; 82 var lastSlice = currSubRow[currSubRow.length - 1];
78 if (slice.start >= lastSlice.start + lastSlice.duration) { 83 if (slice.start >= lastSlice.start + lastSlice.duration) {
79 currSubRow.push(slice); 84 currSubRow.push(slice);
80 return; 85 return;
81 } 86 }
82 } 87 }
83 this.nonNestedSubRows.push([slice]); 88 this.nonNestedSubRows.push([slice]);
84 }, 89 },
85 90
86 updateBounds: function() { 91 updateBounds: function() {
James Hawkins 2011/08/01 18:28:49 Document this method.
nduca 2011/08/01 20:52:22 Done.
87 var slices = this.subRows[0]; 92 var values = [];
88 if (slices.length != 0) { 93 var slices;
89 this.minTimestamp = slices[0].start; 94 if (this.subRows[0].length != 0) {
90 this.maxTimestamp = slices[slices.length - 1].end; 95 slices = this.subRows[0];
96 values.push(slices[0].start);
97 values.push(slices[slices.length - 1].end);
98 }
99 for (var i = 0; i < this.nonNestedSubRows.length; ++i) {
100 slices = this.nonNestedSubRows[i];
101 values.push(slices[0].start);
102 values.push(slices[slices.length - 1].end);
103 }
104 if (values.length) {
105 this.minTimestamp = Math.min.apply(Math, values);
106 this.maxTimestamp = Math.max.apply(Math, values);
91 } else { 107 } else {
92 this.minTimestamp = undefined; 108 this.minTimestamp = undefined;
93 this.maxTimestamp = undefined; 109 this.maxTimestamp = undefined;
94 } 110 }
95 } 111 }
96 112
97 }; 113 };
114 /**
James Hawkins 2011/08/01 18:28:49 Add blank line between methods.
nduca 2011/08/01 20:52:22 Done.
115 * Comparison between threads that orders first by pid,
116 * then by names, then by tid.
117 */
118 TimelineThread.compare = function(x,y) {
119 if(x.parent.pid == y.parent.pid) {
James Hawkins 2011/08/01 18:28:49 You could save a lot of indentation by reversing t
James Hawkins 2011/08/01 18:28:49 Space after if.
nduca 2011/08/01 20:52:22 Done.
120 if (x.name && y.name) {
121 var tmp = x.name.localeCompare(y.name);
122 if (tmp == 0)
123 return x.tid - y.tid;
124 return tmp;
125 } else if(x.name) {
126 return -1;
127 } else if(y.name){
128 return 1;
129 } else {
130 return x.tid - y.tid;
131 }
132 } else {
133 return x.parent.pid - y.parent.pid;
134 }
135 };
136
98 137
99 /** 138 /**
100 * The TimelineProcess represents a single process in the 139 * The TimelineProcess represents a single process in the
101 * trace. Right now, we keep this around purely for bookkeeping 140 * trace. Right now, we keep this around purely for bookkeeping
102 * reasons. 141 * reasons.
103 * @constructor 142 * @constructor
104 */ 143 */
105 function TimelineProcess(pid) { 144 function TimelineProcess(pid) {
106 this.pid = pid; 145 this.pid = pid;
107 this.threads = {}; 146 this.threads = {};
108 }; 147 };
109 148
110 TimelineProcess.prototype = { 149 TimelineProcess.prototype = {
111 getThread: function(tid) { 150 getThread: function(tid) {
112 if (!this.threads[tid]) 151 if (!this.threads[tid])
113 this.threads[tid] = new TimelineThread(this, tid); 152 this.threads[tid] = new TimelineThread(this, tid);
114 return this.threads[tid]; 153 return this.threads[tid];
115 } 154 }
116 }; 155 };
117 156
118 /** 157 /**
119 * Builds a model from an array of TraceEvent objects. 158 * Builds a model from an array of TraceEvent objects.
120 * @param {Array} events An array of TraceEvents created by 159 * @param {Array} events An array of TraceEvents created by
121 * TraceEvent.ToJSON(). 160 * TraceEvent.ToJSON().
122 * @constructor 161 * @constructor
123 */ 162 */
124 function TimelineModel(events) { 163 function TimelineModel(events) {
125 this.processes = {}; 164 this.processes = {};
165 this.importErrors = [];
126 166
127 if (events) 167 if (events)
128 this.importEvents(events); 168 this.importEvents(events);
129 } 169 }
130 170
131 TimelineModel.prototype = { 171 TimelineModel.prototype = {
132 __proto__: cr.EventTarget.prototype, 172 __proto__: cr.EventTarget.prototype,
133 173
134 getProcess: function(pid) { 174 getProcess: function(pid) {
135 if (!this.processes[pid]) 175 if (!this.processes[pid])
136 this.processes[pid] = new TimelineProcess(pid); 176 this.processes[pid] = new TimelineProcess(pid);
137 return this.processes[pid]; 177 return this.processes[pid];
138 }, 178 },
139 179
140 /** 180 /**
141 * The import takes an array of json-ified TraceEvents and adds them into 181 * The import takes an array of json-ified TraceEvents and adds them into
142 * the TimelineModel as processes, threads, and slices. 182 * the TimelineModel as processes, threads, and slices.
143 */ 183 */
144 importEvents: function(events) { 184 importEvents: function(events) {
145 // A ptid is a pid and tid joined together x:y fashion, eg 1024:130 185 // A ptid is a pid and tid joined together x:y fashion, eg 1024:130
146 // The ptid is a unique key for a thread in the trace. 186 // The ptid is a unique key for a thread in the trace.
147 187 this.importErrors = [];
148 188
149 // Threadstate 189 // Threadstate
150 const numColorIds = 30; 190 const numColorIds = 30;
151 function ThreadState(tid) { 191 function ThreadState(tid) {
152 this.openSlices = []; 192 this.openSlices = [];
153 this.openNonNestedSlices = {}; 193 this.openNonNestedSlices = {};
154 } 194 }
155 var threadStateByPTID = {}; 195 var threadStateByPTID = {};
156 196
157 var nameToColorMap = {}; 197 var nameToColorMap = {};
(...skipping 23 matching lines...) Expand all
181 var slice = 221 var slice =
182 { index: eI, 222 { index: eI,
183 slice: new TimelineSlice(event.name, colorId, event.ts, 223 slice: new TimelineSlice(event.name, colorId, event.ts,
184 event.args) }; 224 event.args) };
185 if (event.args['ui-nest'] === '0') { 225 if (event.args['ui-nest'] === '0') {
186 var sliceID = event.name; 226 var sliceID = event.name;
187 for (var x in event.args) { 227 for (var x in event.args) {
188 sliceID += ';' + event.args[x]; 228 sliceID += ';' + event.args[x];
189 } 229 }
190 if (state.openNonNestedSlices[sliceID]) 230 if (state.openNonNestedSlices[sliceID])
191 console.log('Event ' + sliceID + ' already open.'); 231 this.importErrors.push('Event ' + sliceID + ' already open.');
192 state.openNonNestedSlices[sliceID] = slice; 232 state.openNonNestedSlices[sliceID] = slice;
193 } else 233 } else
194 state.openSlices.push(slice); 234 state.openSlices.push(slice);
195 } else if (event.ph == 'E') { 235 } else if (event.ph == 'E') {
196 if (event.args['ui-nest'] === '0') { 236 if (event.args['ui-nest'] === '0') {
197 var sliceID = event.name; 237 var sliceID = event.name;
198 for (var x in event.args) { 238 for (var x in event.args) {
199 sliceID += ';' + event.args[x]; 239 sliceID += ';' + event.args[x];
200 } 240 }
201 var slice = state.openNonNestedSlices[sliceID]; 241 var slice = state.openNonNestedSlices[sliceID];
(...skipping 20 matching lines...) Expand all
222 262
223 // Add the slice to the subSlices array of its parent. 263 // Add the slice to the subSlices array of its parent.
224 if (state.openSlices.length) { 264 if (state.openSlices.length) {
225 var parentSlice = state.openSlices[state.openSlices.length - 1]; 265 var parentSlice = state.openSlices[state.openSlices.length - 1];
226 parentSlice.slice.subSlices.push(slice); 266 parentSlice.slice.subSlices.push(slice);
227 } 267 }
228 } 268 }
229 } else if (event.ph == 'I') { 269 } else if (event.ph == 'I') {
230 // TODO(nduca): Implement parsing of immediate events. 270 // TODO(nduca): Implement parsing of immediate events.
231 console.log('Parsing of I-type events not implemented.'); 271 console.log('Parsing of I-type events not implemented.');
272 } else if (event.ph == 'M') {
273 if (event.name == 'thread_name') {
274 var thread = this.getProcess(event.pid).getThread(event.tid);
275 thread.name = event.args.name;
276 } else {
277 this.importErrors.push('Unrecognized metadata name: ' + event.name);
278 }
232 } else { 279 } else {
233 throw new Error('Unrecognized event phase: ' + event.ph + 280 this.importErrors.push('Unrecognized event phase: ' + event.ph +
234 '(' + event.name + ')'); 281 '(' + event.name + ')');
235 } 282 }
236 } 283 }
237 284 this.pruneEmptyThreads();
238 this.updateBounds(); 285 this.updateBounds();
239 286
240 // Add end events for any events that are still on the stack. These 287 // Add end events for any events that are still on the stack. These
241 // are events that were still open when trace was ended, and can often 288 // are events that were still open when trace was ended, and can often
242 // indicate deadlock behavior. 289 // indicate deadlock behavior.
243 for (var ptid in threadStateByPTID) { 290 for (var ptid in threadStateByPTID) {
244 var state = threadStateByPTID[ptid]; 291 var state = threadStateByPTID[ptid];
245 while (state.openSlices.length > 0) { 292 while (state.openSlices.length > 0) {
246 var slice = state.openSlices.pop(); 293 var slice = state.openSlices.pop();
247 slice.slice.duration = this.maxTimestamp - slice.slice.start; 294 slice.slice.duration = this.maxTimestamp - slice.slice.start;
(...skipping 13 matching lines...) Expand all
261 } 308 }
262 } 309 }
263 310
264 this.shiftWorldToMicroseconds(); 311 this.shiftWorldToMicroseconds();
265 312
266 var boost = (this.maxTimestamp - this.minTimestamp) * 0.15; 313 var boost = (this.maxTimestamp - this.minTimestamp) * 0.15;
267 this.minTimestamp = this.minTimestamp - boost; 314 this.minTimestamp = this.minTimestamp - boost;
268 this.maxTimestamp = this.maxTimestamp + boost; 315 this.maxTimestamp = this.maxTimestamp + boost;
269 }, 316 },
270 317
318 /**
319 * Removes threads from the model that have no subrows.
320 */
321 pruneEmptyThreads: function() {
322 for (var pid in this.processes) {
323 var process = this.processes[pid];
324 var prunedThreads = [];
325 for (var tid in process.threads) {
326 var thread = process.threads[tid];
327 if (thread.subRows[0].length || thread.nonNestedSubRows.legnth)
328 prunedThreads.push(thread);
329 }
330 process.threads = prunedThreads;
331 }
332 },
333
271 updateBounds: function() { 334 updateBounds: function() {
272 var wmin = Infinity; 335 var wmin = Infinity;
273 var wmax = -wmin; 336 var wmax = -wmin;
274 var threads = this.getAllThreads(); 337 var threads = this.getAllThreads();
275 for (var tI = 0; tI < threads.length; tI++) { 338 for (var tI = 0; tI < threads.length; tI++) {
276 var thread = threads[tI]; 339 var thread = threads[tI];
277 thread.updateBounds(); 340 thread.updateBounds();
278 if (thread.minTimestamp && thread.maxTimestamp) { 341 if (thread.minTimestamp != undefined &&
342 thread.maxTimestamp != undefined) {
279 wmin = Math.min(wmin, thread.minTimestamp); 343 wmin = Math.min(wmin, thread.minTimestamp);
280 wmax = Math.max(wmax, thread.maxTimestamp); 344 wmax = Math.max(wmax, thread.maxTimestamp);
281 } 345 }
282 } 346 }
283 this.minTimestamp = wmin; 347 this.minTimestamp = wmin;
284 this.maxTimestamp = wmax; 348 this.maxTimestamp = wmax;
285 }, 349 },
286 350
287 shiftWorldToMicroseconds: function() { 351 shiftWorldToMicroseconds: function() {
288 var timeBase = this.minTimestamp; 352 var timeBase = this.minTimestamp;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 384
321 }; 385 };
322 386
323 return { 387 return {
324 TimelineSlice: TimelineSlice, 388 TimelineSlice: TimelineSlice,
325 TimelineThread: TimelineThread, 389 TimelineThread: TimelineThread,
326 TimelineProcess: TimelineProcess, 390 TimelineProcess: TimelineProcess,
327 TimelineModel: TimelineModel 391 TimelineModel: TimelineModel
328 }; 392 };
329 }); 393 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/gpu_internals/timeline.js ('k') | chrome/browser/resources/gpu_internals/timeline_track.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698