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

Side by Side Diff: chrome/browser/resources/tracing/linux_perf_importer.js

Issue 10543144: Remove old tracing code now that it has moved to third_party. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 6 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview Imports text files in the Linux event trace format into the
7 * timeline model. This format is output both by sched_trace and by Linux's perf
8 * tool.
9 *
10 * This importer assumes the events arrive as a string. The unit tests provide
11 * examples of the trace format.
12 *
13 * Linux scheduler traces use a definition for 'pid' that is different than
14 * tracing uses. Whereas tracing uses pid to identify a specific process, a pid
15 * in a linux trace refers to a specific thread within a process. Within this
16 * file, we the definition used in Linux traces, as it improves the importing
17 * code's readability.
18 */
19 cr.define('tracing', function() {
20 /**
21 * Represents the scheduling state for a single thread.
22 * @constructor
23 */
24 function CpuState(cpu) {
25 this.cpu = cpu;
26 }
27
28 CpuState.prototype = {
29 __proto__: Object.prototype,
30
31 /**
32 * Switches the active pid on this Cpu. If necessary, add a TimelineSlice
33 * to the cpu representing the time spent on that Cpu since the last call to
34 * switchRunningLinuxPid.
35 */
36 switchRunningLinuxPid: function(importer, prevState, ts, pid, comm, prio) {
37 // Generate a slice if the last active pid was not the idle task
38 if (this.lastActivePid !== undefined && this.lastActivePid != 0) {
39 var duration = ts - this.lastActiveTs;
40 var thread = importer.threadsByLinuxPid[this.lastActivePid];
41 if (thread)
42 name = thread.userFriendlyName;
43 else
44 name = this.lastActiveComm;
45
46 var slice = new tracing.TimelineSlice(name,
47 tracing.getStringColorId(name),
48 this.lastActiveTs,
49 {
50 comm: this.lastActiveComm,
51 tid: this.lastActivePid,
52 prio: this.lastActivePrio,
53 stateWhenDescheduled: prevState
54 },
55 duration);
56 this.cpu.slices.push(slice);
57 }
58
59 this.lastActiveTs = ts;
60 this.lastActivePid = pid;
61 this.lastActiveComm = comm;
62 this.lastActivePrio = prio;
63 }
64 };
65
66 /**
67 * Imports linux perf events into a specified model.
68 * @constructor
69 */
70 function LinuxPerfImporter(model, events, isAdditionalImport) {
71 this.isAdditionalImport_ = isAdditionalImport;
72 this.model_ = model;
73 this.events_ = events;
74 this.clockSyncRecords_ = [];
75 this.cpuStates_ = {};
76 this.kernelThreadStates_ = {};
77 this.buildMapFromLinuxPidsToTimelineThreads();
78 this.lineNumber = -1;
79 }
80
81 TestExports = {};
82
83 // Matches the generic trace record:
84 // <idle>-0 [001] 1.23: sched_switch
85 var lineRE = /^\s*(.+?)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;
86 TestExports.lineRE = lineRE;
87
88 // Matches the sched_switch record
89 var schedSwitchRE = new RegExp(
90 'prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) prev_state=(\\S) ==> ' +
91 'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)');
92 TestExports.schedSwitchRE = schedSwitchRE;
93
94 // Matches the sched_wakeup record
95 var schedWakeupRE =
96 /comm=(.+) pid=(\d+) prio=(\d+) success=(\d+) target_cpu=(\d+)/;
97 TestExports.schedWakeupRE = schedWakeupRE;
98
99 // Matches the trace_event_clock_sync record
100 // 0: trace_event_clock_sync: parent_ts=19581477508
101 var traceEventClockSyncRE = /trace_event_clock_sync: parent_ts=(\d+\.?\d*)/;
102 TestExports.traceEventClockSyncRE = traceEventClockSyncRE;
103
104 // Matches the workqueue_execute_start record
105 // workqueue_execute_start: work struct c7a8a89c: function MISRWrapper
106 var workqueueExecuteStartRE = /work struct (.+): function (\S+)/;
107
108 // Matches the workqueue_execute_start record
109 // workqueue_execute_end: work struct c7a8a89c
110 var workqueueExecuteEndRE = /work struct (.+)/;
111
112 // Some kernel trace events are manually classified in slices and
113 // hand-assigned a pseudo PID+TID.
114 var pseudoKernelPID = 0;
115 TestExports.pseudoKernelPID = pseudoKernelPID;
116 var pseudoI915GemObjectTID = 1;
117 TestExports.pseudoI915GemObjectTID = pseudoI915GemObjectTID;
118 var pseudoI915GemRingTID = 2;
119 TestExports.pseudoI915GemRingTID = pseudoI915GemRingTID;
120 var pseudoI915FlipTID = 3;
121 TestExports.pseudoI915FlipTID = pseudoI915FlipTID;
122 var pseudoI915RegTID = 4;
123 TestExports.pseudoI915RegTID = pseudoI915RegTID;
124 var pseudoVblankTID = 5;
125 TestExports.pseudoVblankTID = pseudoVblankTID;
126
127 /**
128 * Guesses whether the provided events is a Linux perf string.
129 * Looks for the magic string "# tracer" at the start of the file,
130 * or the typical task-pid-cpu-timestamp-function sequence of a typical
131 * trace's body.
132 *
133 * @return {boolean} True when events is a linux perf array.
134 */
135 LinuxPerfImporter.canImport = function(events) {
136 if (!(typeof(events) === 'string' || events instanceof String))
137 return false;
138
139 if (/^# tracer:/.exec(events))
140 return true;
141
142 var m = /^(.+)\n/.exec(events);
143 if (m)
144 events = m[1];
145 if (lineRE.exec(events))
146 return true;
147
148 return false;
149 };
150
151 LinuxPerfImporter.prototype = {
152 __proto__: Object.prototype,
153
154 /**
155 * Precomputes a lookup table from linux pids back to existing
156 * TimelineThreads. This is used during importing to add information to each
157 * timeline thread about whether it was running, descheduled, sleeping, et
158 * cetera.
159 */
160 buildMapFromLinuxPidsToTimelineThreads: function() {
161 this.threadsByLinuxPid = {};
162 this.model_.getAllThreads().forEach(
163 function(thread) {
164 this.threadsByLinuxPid[thread.tid] = thread;
165 }.bind(this));
166 },
167
168 /**
169 * @return {CpuState} A CpuState corresponding to the given cpuNumber.
170 */
171 getOrCreateCpuState: function(cpuNumber) {
172 if (!this.cpuStates_[cpuNumber]) {
173 var cpu = this.model_.getOrCreateCpu(cpuNumber);
174 this.cpuStates_[cpuNumber] = new CpuState(cpu);
175 }
176 return this.cpuStates_[cpuNumber];
177 },
178
179 /**
180 * @return {TimelinThread} A thread corresponding to the kernelThreadName.
181 */
182 getOrCreateKernelThread: function(kernelThreadName, opt_pid, opt_tid) {
183 if (!this.kernelThreadStates_[kernelThreadName]) {
184 var pid = opt_pid;
185 if (pid == undefined) {
186 pid = /.+-(\d+)/.exec(kernelThreadName)[1];
187 pid = parseInt(pid, 10);
188 }
189 var tid = opt_tid;
190 if (tid == undefined)
191 tid = pid;
192
193 var thread = this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);
194 thread.name = kernelThreadName;
195 this.kernelThreadStates_[kernelThreadName] = {
196 pid: pid,
197 thread: thread,
198 openSlice: undefined,
199 openSliceTS: undefined
200 };
201 this.threadsByLinuxPid[pid] = thread;
202 }
203 return this.kernelThreadStates_[kernelThreadName];
204 },
205
206 /**
207 * Imports the data in this.events_ into model_.
208 */
209 importEvents: function() {
210 this.importCpuData();
211 if (!this.alignClocks())
212 return;
213 this.buildPerThreadCpuSlicesFromCpuState();
214 },
215
216 /**
217 * Called by the TimelineModel after all other importers have imported their
218 * events.
219 */
220 finalizeImport: function() {
221 },
222
223 /**
224 * Builds the cpuSlices array on each thread based on our knowledge of what
225 * each Cpu is doing. This is done only for TimelineThreads that are
226 * already in the model, on the assumption that not having any traced data
227 * on a thread means that it is not of interest to the user.
228 */
229 buildPerThreadCpuSlicesFromCpuState: function() {
230 // Push the cpu slices to the threads that they run on.
231 for (var cpuNumber in this.cpuStates_) {
232 var cpuState = this.cpuStates_[cpuNumber];
233 var cpu = cpuState.cpu;
234
235 for (var i = 0; i < cpu.slices.length; i++) {
236 var slice = cpu.slices[i];
237
238 var thread = this.threadsByLinuxPid[slice.args.tid];
239 if (!thread)
240 continue;
241 if (!thread.tempCpuSlices)
242 thread.tempCpuSlices = [];
243 thread.tempCpuSlices.push(slice);
244 }
245 }
246
247 // Create slices for when the thread is not running.
248 var runningId = tracing.getColorIdByName('running');
249 var runnableId = tracing.getColorIdByName('runnable');
250 var sleepingId = tracing.getColorIdByName('sleeping');
251 var ioWaitId = tracing.getColorIdByName('iowait');
252 this.model_.getAllThreads().forEach(function(thread) {
253 if (!thread.tempCpuSlices)
254 return;
255 var origSlices = thread.tempCpuSlices;
256 delete thread.tempCpuSlices;
257
258 origSlices.sort(function(x, y) {
259 return x.start - y.start;
260 });
261
262 // Walk the slice list and put slices between each original slice
263 // to show when the thread isn't running
264 var slices = [];
265 if (origSlices.length) {
266 var slice = origSlices[0];
267 slices.push(new tracing.TimelineSlice('Running', runningId,
268 slice.start, {}, slice.duration));
269 }
270 for (var i = 1; i < origSlices.length; i++) {
271 var prevSlice = origSlices[i - 1];
272 var nextSlice = origSlices[i];
273 var midDuration = nextSlice.start - prevSlice.end;
274 if (prevSlice.args.stateWhenDescheduled == 'S') {
275 slices.push(new tracing.TimelineSlice('Sleeping', sleepingId,
276 prevSlice.end, {}, midDuration));
277 } else if (prevSlice.args.stateWhenDescheduled == 'R') {
278 slices.push(new tracing.TimelineSlice('Runnable', runnableId,
279 prevSlice.end, {}, midDuration));
280 } else if (prevSlice.args.stateWhenDescheduled == 'D') {
281 slices.push(new tracing.TimelineSlice(
282 'Uninterruptible Sleep', ioWaitId,
283 prevSlice.end, {}, midDuration));
284 } else if (prevSlice.args.stateWhenDescheduled == 'T') {
285 slices.push(new tracing.TimelineSlice('__TASK_STOPPED', ioWaitId,
286 prevSlice.end, {}, midDuration));
287 } else if (prevSlice.args.stateWhenDescheduled == 't') {
288 slices.push(new tracing.TimelineSlice('debug', ioWaitId,
289 prevSlice.end, {}, midDuration));
290 } else if (prevSlice.args.stateWhenDescheduled == 'Z') {
291 slices.push(new tracing.TimelineSlice('Zombie', ioWaitId,
292 prevSlice.end, {}, midDuration));
293 } else if (prevSlice.args.stateWhenDescheduled == 'X') {
294 slices.push(new tracing.TimelineSlice('Exit Dead', ioWaitId,
295 prevSlice.end, {}, midDuration));
296 } else if (prevSlice.args.stateWhenDescheduled == 'x') {
297 slices.push(new tracing.TimelineSlice('Task Dead', ioWaitId,
298 prevSlice.end, {}, midDuration));
299 } else if (prevSlice.args.stateWhenDescheduled == 'W') {
300 slices.push(new tracing.TimelineSlice('WakeKill', ioWaitId,
301 prevSlice.end, {}, midDuration));
302 } else if (prevSlice.args.stateWhenDescheduled == 'D|W') {
303 slices.push(new tracing.TimelineSlice(
304 'Uninterruptable Sleep | WakeKill', ioWaitId,
305 prevSlice.end, {}, midDuration));
306 } else {
307 throw 'Unrecognized state: ' + prevSlice.args.stateWhenDescheduled;
308 }
309
310 slices.push(new tracing.TimelineSlice('Running', runningId,
311 nextSlice.start, {}, nextSlice.duration));
312 }
313 thread.cpuSlices = slices;
314 });
315 },
316
317 /**
318 * Walks the slices stored on this.cpuStates_ and adjusts their timestamps
319 * based on any alignment metadata we discovered.
320 */
321 alignClocks: function() {
322 if (this.clockSyncRecords_.length == 0) {
323 // If this is an additional import, and no clock syncing records were
324 // found, then abort the import. Otherwise, just skip clock alignment.
325 if (!this.isAdditionalImport_)
326 return;
327
328 // Remove the newly imported CPU slices from the model.
329 this.abortImport();
330 return false;
331 }
332
333 // Shift all the slice times based on the sync record.
334 var sync = this.clockSyncRecords_[0];
335 // NB: parentTS of zero denotes no times-shift; this is
336 // used when user and kernel event clocks are identical.
337 if (sync.parentTS == 0 || sync.parentTS == sync.perfTS)
338 return true;
339 var timeShift = sync.parentTS - sync.perfTS;
340 for (var cpuNumber in this.cpuStates_) {
341 var cpuState = this.cpuStates_[cpuNumber];
342 var cpu = cpuState.cpu;
343
344 for (var i = 0; i < cpu.slices.length; i++) {
345 var slice = cpu.slices[i];
346 slice.start = slice.start + timeShift;
347 slice.duration = slice.duration;
348 }
349
350 for (var counterName in cpu.counters) {
351 var counter = cpu.counters[counterName];
352 for (var sI = 0; sI < counter.timestamps.length; sI++)
353 counter.timestamps[sI] = (counter.timestamps[sI] + timeShift);
354 }
355 }
356 for (var kernelThreadName in this.kernelThreadStates_) {
357 var kthread = this.kernelThreadStates_[kernelThreadName];
358 var thread = kthread.thread;
359 for (var i = 0; i < thread.subRows[0].length; i++) {
360 thread.subRows[0][i].start += timeShift;
361 }
362 }
363 return true;
364 },
365
366 /**
367 * Removes any data that has been added to the model because of an error
368 * detected during the import.
369 */
370 abortImport: function() {
371 if (this.pushedEventsToThreads)
372 throw 'Cannot abort, have alrady pushedCpuDataToThreads.';
373
374 for (var cpuNumber in this.cpuStates_)
375 delete this.model_.cpus[cpuNumber];
376 for (var kernelThreadName in this.kernelThreadStates_) {
377 var kthread = this.kernelThreadStates_[kernelThreadName];
378 var thread = kthread.thread;
379 var process = thread.parent;
380 delete process.threads[thread.tid];
381 delete this.model_.processes[process.pid];
382 }
383 this.model_.importErrors.push(
384 'Cannot import kernel trace without a clock sync.');
385 },
386
387 /**
388 * Records the fact that a pid has become runnable. This data will
389 * eventually get used to derive each thread's cpuSlices array.
390 */
391 markPidRunnable: function(ts, pid, comm, prio) {
392 // TODO(nduca): implement this functionality.
393 },
394
395 importError: function(message) {
396 this.model_.importErrors.push('Line ' + (this.lineNumber + 1) +
397 ': ' + message);
398 },
399
400 malformedEvent: function(eventName) {
401 this.importError('Malformed ' + eventName + ' event');
402 },
403
404 cpuStateSlice: function(ts, targetCpuNumber, eventType, cpuState) {
405 var targetCpu = this.getOrCreateCpuState(targetCpuNumber);
406 var powerCounter;
407 if (eventType != '1') {
408 this.importError('Don\'t understand power_start events of type ' +
409 eventType);
410 return;
411 }
412 powerCounter = targetCpu.cpu.getOrCreateCounter('', 'C-State');
413 if (powerCounter.numSeries == 0) {
414 powerCounter.seriesNames.push('state');
415 powerCounter.seriesColors.push(
416 tracing.getStringColorId(powerCounter.name + '.' + 'state'));
417 }
418 powerCounter.timestamps.push(ts);
419 powerCounter.samples.push(cpuState);
420 },
421
422 cpuIdleSlice: function(ts, targetCpuNumber, cpuState) {
423 var targetCpu = this.getOrCreateCpuState(targetCpuNumber);
424 var powerCounter = targetCpu.cpu.getOrCreateCounter('', 'C-State');
425 if (powerCounter.numSeries == 0) {
426 powerCounter.seriesNames.push('state');
427 powerCounter.seriesColors.push(
428 tracing.getStringColorId(powerCounter.name));
429 }
430 // NB: 4294967295/-1 means an exit from the current state
431 if (cpuState != 4294967295)
432 powerCounter.samples.push(cpuState);
433 else
434 powerCounter.samples.push(0);
435 powerCounter.timestamps.push(ts);
436 },
437
438 cpuFrequencySlice: function(ts, targetCpuNumber, powerState) {
439 var targetCpu = this.getOrCreateCpuState(targetCpuNumber);
440 var powerCounter =
441 targetCpu.cpu.getOrCreateCounter('', 'Clock Frequency');
442 if (powerCounter.numSeries == 0) {
443 powerCounter.seriesNames.push('state');
444 powerCounter.seriesColors.push(
445 tracing.getStringColorId(powerCounter.name + '.' + 'state'));
446 }
447 powerCounter.timestamps.push(ts);
448 powerCounter.samples.push(powerState);
449 },
450
451 i915GemObjectSlice: function(ts, eventName, obj, args) {
452 var kthread = this.getOrCreateKernelThread('i915_gem', pseudoKernelPID,
453 pseudoI915GemObjectTID);
454 kthread.openSlice = eventName + ':' + obj;
455 var slice = new tracing.TimelineSlice(kthread.openSlice,
456 tracing.getStringColorId(kthread.openSlice), ts, args, 0);
457
458 kthread.thread.subRows[0].push(slice);
459 },
460
461 i915GemRingSlice: function(ts, eventName, dev, ring, args) {
462 var kthread = this.getOrCreateKernelThread('i915_gem_ring',
463 pseudoKernelPID, pseudoI915GemRingTID);
464 kthread.openSlice = eventName + ':' + dev + '.' + ring;
465 var slice = new tracing.TimelineSlice(kthread.openSlice,
466 tracing.getStringColorId(kthread.openSlice), ts, args, 0);
467
468 kthread.thread.subRows[0].push(slice);
469 },
470
471 i915RegSlice: function(ts, eventName, reg, args) {
472 var kthread = this.getOrCreateKernelThread('i915_reg',
473 pseudoKernelPID, pseudoI915RegTID);
474 kthread.openSlice = eventName + ':' + reg;
475 var slice = new tracing.TimelineSlice(kthread.openSlice,
476 tracing.getStringColorId(kthread.openSlice), ts, args, 0);
477
478 kthread.thread.subRows[0].push(slice);
479 },
480
481 i915OpenFlipSlice: function(ts, obj, plane) {
482 // use i915_obj_plane?
483 var kthread = this.getOrCreateKernelThread('i915_flip',
484 pseudoKernelPID, pseudoI915FlipTID);
485 kthread.openSliceTS = ts;
486 kthread.openSlice = 'flip:' + obj + '/' + plane;
487 },
488
489 i915CloseFlipSlice: function(ts, args) {
490 // use i915_obj_plane?
491 var kthread = this.getOrCreateKernelThread('i915_flip',
492 pseudoKernelPID, pseudoI915FlipTID);
493 if (kthread.openSlice) {
494 var slice = new tracing.TimelineSlice(kthread.openSlice,
495 tracing.getStringColorId(kthread.openSlice),
496 kthread.openSliceTS,
497 args,
498 ts - kthread.openSliceTS);
499
500 kthread.thread.subRows[0].push(slice);
501 }
502 kthread.openSlice = undefined;
503 },
504
505 drmVblankSlice: function(ts, eventName, args) {
506 var kthread = this.getOrCreateKernelThread('drm_vblank',
507 pseudoKernelPID, pseudoVblankTID);
508 kthread.openSlice = eventName;
509 var slice = new tracing.TimelineSlice(kthread.openSlice,
510 tracing.getStringColorId(kthread.openSlice), ts, args, 0);
511
512 kthread.thread.subRows[0].push(slice);
513 },
514
515 /**
516 * Walks the this.events_ structure and creates TimelineCpu objects.
517 */
518 importCpuData: function() {
519 this.lines_ = this.events_.split('\n');
520
521 for (this.lineNumber = 0; this.lineNumber < this.lines_.length;
522 ++this.lineNumber) {
523 var line = this.lines_[this.lineNumber];
524 if (/^#/.exec(line) || line.length == 0)
525 continue;
526 var eventBase = lineRE.exec(line);
527 if (!eventBase) {
528 this.importError('Unrecognized line: ' + line);
529 continue;
530 }
531
532 var cpuState = this.getOrCreateCpuState(parseInt(eventBase[2]));
533 var ts = parseFloat(eventBase[3]) * 1000;
534
535 var eventName = eventBase[4];
536
537 switch (eventName) {
538 case 'sched_switch':
539 var event = schedSwitchRE.exec(eventBase[5]);
540 if (!event) {
541 this.malformedEvent(eventName);
542 continue;
543 }
544
545 var prevState = event[4];
546 var nextComm = event[5];
547 var nextPid = parseInt(event[6]);
548 var nextPrio = parseInt(event[7]);
549 cpuState.switchRunningLinuxPid(
550 this, prevState, ts, nextPid, nextComm, nextPrio);
551 break;
552 case 'sched_wakeup':
553 var event = schedWakeupRE.exec(eventBase[5]);
554 if (!event) {
555 this.malformedEvent(eventName);
556 continue;
557 }
558
559 var comm = event[1];
560 var pid = parseInt(event[2]);
561 var prio = parseInt(event[3]);
562 this.markPidRunnable(ts, pid, comm, prio);
563 break;
564 case 'power_start': // NB: old-style power event, deprecated
565 var event = /type=(\d+) state=(\d) cpu_id=(\d)+/.exec(eventBase[5]);
566 if (!event) {
567 this.malformedEvent(eventName);
568 continue;
569 }
570
571 var targetCpuNumber = parseInt(event[3]);
572 var cpuState = parseInt(event[2]);
573 this.cpuStateSlice(ts, targetCpuNumber, event[1], cpuState);
574 break;
575 case 'power_frequency': // NB: old-style power event, deprecated
576 var event = /type=(\d+) state=(\d+) cpu_id=(\d)+/.exec(
577 eventBase[5]);
578 if (!event) {
579 this.malformedEvent(eventName);
580 continue;
581 }
582
583 var targetCpuNumber = parseInt(event[3]);
584 var powerState = parseInt(event[2]);
585 this.cpuFrequencySlice(ts, targetCpuNumber, powerState);
586 break;
587 case 'cpu_frequency':
588 var event = /state=(\d+) cpu_id=(\d)+/.exec(eventBase[5]);
589 if (!event) {
590 this.malformedEvent(eventName);
591 continue;
592 }
593
594 var targetCpuNumber = parseInt(event[2]);
595 var powerState = parseInt(event[1]);
596 this.cpuFrequencySlice(ts, targetCpuNumber, powerState);
597 break;
598 case 'cpu_idle':
599 var event = /state=(\d+) cpu_id=(\d)+/.exec(eventBase[5]);
600 if (!event) {
601 this.malformedEvent(eventName);
602 continue;
603 }
604
605 var targetCpuNumber = parseInt(event[2]);
606 var cpuState = parseInt(event[1]);
607 this.cpuIdleSlice(ts, targetCpuNumber, cpuState);
608 break;
609 case 'workqueue_execute_start':
610 var event = workqueueExecuteStartRE.exec(eventBase[5]);
611 if (!event) {
612 this.malformedEvent(eventName);
613 continue;
614 }
615
616 var kthread = this.getOrCreateKernelThread(eventBase[1]);
617 kthread.openSliceTS = ts;
618 kthread.openSlice = event[2];
619 break;
620 case 'workqueue_execute_end':
621 var event = workqueueExecuteEndRE.exec(eventBase[5]);
622 if (!event) {
623 this.malformedEvent(eventName);
624 continue;
625 }
626
627 var kthread = this.getOrCreateKernelThread(eventBase[1]);
628 if (kthread.openSlice) {
629 var slice = new tracing.TimelineSlice(kthread.openSlice,
630 tracing.getStringColorId(kthread.openSlice),
631 kthread.openSliceTS,
632 {},
633 ts - kthread.openSliceTS);
634
635 kthread.thread.subRows[0].push(slice);
636 }
637 kthread.openSlice = undefined;
638 break;
639 case 'i915_gem_object_create':
640 var event = /obj=(.+), size=(\d+)/.exec(eventBase[5]);
641 if (!event) {
642 this.malformedEvent(eventName);
643 continue;
644 }
645
646 var obj = event[1];
647 var size = parseInt(event[2]);
648 this.i915GemObjectSlice(ts, eventName, obj,
649 {
650 obj: obj,
651 size: size
652 });
653 break;
654 case 'i915_gem_object_bind':
655 case 'i915_gem_object_unbind':
656 // TODO(sleffler) mappable
657 var event = /obj=(.+), offset=(.+), size=(\d+)/.exec(eventBase[5]);
658 if (!event) {
659 this.malformedEvent(eventName);
660 continue;
661 }
662
663 var obj = event[1];
664 var offset = event[2];
665 var size = parseInt(event[3]);
666 this.i915ObjectGemSlice(ts, eventName + ':' + obj,
667 {
668 obj: obj,
669 offset: offset,
670 size: size
671 });
672 break;
673 case 'i915_gem_object_change_domain':
674 var event = /obj=(.+), read=(.+), write=(.+)/.exec(eventBase[5]);
675 if (!event) {
676 this.malformedEvent(eventName);
677 continue;
678 }
679
680 var obj = event[1];
681 var read = event[2];
682 var write = event[3];
683 this.i915GemObjectSlice(ts, eventName, obj,
684 {
685 obj: obj,
686 read: read,
687 write: write
688 });
689 break;
690 case 'i915_gem_object_pread':
691 case 'i915_gem_object_pwrite':
692 var event = /obj=(.+), offset=(\d+), len=(\d+)/.exec(eventBase[5]);
693 if (!event) {
694 this.malformedEvent(eventName);
695 continue;
696 }
697
698 var obj = event[1];
699 var offset = parseInt(event[2]);
700 var len = parseInt(event[3]);
701 this.i915GemObjectSlice(ts, eventName, obj,
702 {
703 obj: obj,
704 offset: offset,
705 len: len
706 });
707 break;
708 case 'i915_gem_object_fault':
709 // TODO(sleffler) writable
710 var event = /obj=(.+), (.+) index=(\d+)/.exec(eventBase[5]);
711 if (!event) {
712 this.malformedEvent(eventName);
713 continue;
714 }
715
716 var obj = event[1];
717 var type = event[2];
718 var index = parseInt(event[3]);
719 this.i915GemObjectSlice(ts, eventName, obj,
720 {
721 obj: obj,
722 type: type,
723 index: index
724 });
725 break;
726 case 'i915_gem_object_clflush':
727 case 'i915_gem_object_destroy':
728 var event = /obj=(.+)/.exec(eventBase[5]);
729 if (!event) {
730 this.malformedEvent(eventName);
731 continue;
732 }
733
734 var obj = event[1];
735 this.i915GemObjectSlice(ts, eventName, obj,
736 {
737 obj: obj,
738 });
739 break;
740 case 'i915_gem_ring_dispatch':
741 var event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase[5]);
742 if (!event) {
743 this.malformedEvent(eventName);
744 continue;
745 }
746
747 var dev = parseInt(event[1]);
748 var ring = parseInt(event[2]);
749 var seqno = parseInt(event[3]);
750 this.i915GemRingSlice(ts, eventName, dev, ring,
751 {
752 dev: dev,
753 ring: ring,
754 seqno: seqno
755 });
756 break;
757 case 'i915_gem_ring_flush':
758 var event = /dev=(\d+), ring=(\d+), invalidate=(.+), flush=(.+)/.
759 exec(eventBase[5]);
760 if (!event) {
761 this.malformedEvent(eventName);
762 continue;
763 }
764
765 var dev = parseInt(event[1]);
766 var ring = parseInt(event[2]);
767 var invalidate = event[3];
768 var flush = event[4];
769 this.i915GemRingSlice(ts, eventName, dev, ring,
770 {
771 dev: dev,
772 ring: ring,
773 invalidate: invalidate,
774 flush: flush
775 });
776 break;
777 case 'i915_gem_request':
778 case 'i915_gem_request_add':
779 case 'i915_gem_request_complete':
780 case 'i915_gem_request_retire':
781 case 'i915_gem_request_wait_begin':
782 case 'i915_gem_request_wait_end':
783 var event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase[5]);
784 if (!event) {
785 this.malformedEvent(eventName);
786 continue;
787 }
788
789 var dev = parseInt(event[1]);
790 var ring = parseInt(event[2]);
791 var seqno = parseInt(event[3]);
792 this.i915GemRingSlice(ts, eventName, dev, ring,
793 {
794 dev: dev,
795 ring: ring,
796 seqno: seqno
797 });
798 break;
799 case 'i915_ring_wait_begin':
800 case 'i915_ring_wait_end':
801 var event = /dev=(\d+), ring=(\d+)/.exec(eventBase[5]);
802 if (!event) {
803 this.malformedEvent(eventName);
804 continue;
805 }
806
807 var dev = parseInt(event[1]);
808 var ring = parseInt(event[2]);
809 this.i915GemRingSlice(ts, eventName, dev, ring,
810 {
811 dev: dev,
812 ring: ring
813 });
814 break;
815 case 'i915_gem_object_change_domain':
816 var event = /obj=(.+), read=(.+), write=(.+)/.exec(eventBase[5]);
817 if (!event) {
818 this.malformedEvent(eventName);
819 continue;
820 }
821
822 var obj = event[1];
823 var read = event[2];
824 var write = event[3];
825 this.i915GemObjectSlice(ts, eventName, obj,
826 {
827 obj: obj,
828 read: read,
829 write: write
830 });
831 break;
832 case 'i915_reg_rw':
833 var event = /(.+) reg=(.+), len=(.+), val=(.+)/.exec(eventBase[5]);
834 if (!event) {
835 this.malformedEvent(eventName);
836 continue;
837 }
838
839 var rw = event[1];
840 var reg = event[2];
841 var len = event[3];
842 var data = event[3];
843 this.i915RegSlice(ts, rw, reg,
844 {
845 rw: rw,
846 reg: reg,
847 len: len,
848 data: data
849 });
850 break;
851 case 'i915_flip_request':
852 var event = /plane=(\d+), obj=(.+)/.exec(eventBase[5]);
853 if (!event) {
854 this.malformedEvent(eventName);
855 continue;
856 }
857
858 var plane = parseInt(event[1]);
859 var obj = event[2];
860 this.i915OpenFlipSlice(ts, obj, plane);
861 break;
862 case 'i915_flip_complete':
863 var event = /plane=(\d+), obj=(.+)/.exec(eventBase[5]);
864 if (!event) {
865 this.malformedEvent(eventName);
866 continue;
867 }
868
869 var plane = parseInt(event[1]);
870 var obj = event[2];
871 this.i915CloseFlipSlice(ts,
872 {
873 obj: obj,
874 plane: plane
875 });
876 break;
877 case 'drm_vblank_event':
878 var event = /crtc=(\d+), seq=(\d+)/.exec(eventBase[5]);
879 if (!event) {
880 this.malformedEvent(eventName);
881 continue;
882 }
883
884 var crtc = parseInt(event[1]);
885 var seq = parseInt(event[2]);
886 this.drmVblankSlice(ts, 'vblank:' + crtc,
887 {
888 crtc: crtc,
889 seq: seq
890 });
891 break;
892 case '0': // NB: old-style trace markers; deprecated
893 case 'tracing_mark_write':
894 var event = traceEventClockSyncRE.exec(eventBase[5]);
895 if (!event) {
896 this.malformedEvent(eventName);
897 continue;
898 }
899 this.clockSyncRecords_.push({
900 perfTS: ts,
901 parentTS: event[1] * 1000
902 });
903 break;
904 default:
905 console.log('unknown event ' + eventName);
906 break;
907 }
908 }
909 }
910 };
911
912 tracing.TimelineModel.registerImporter(LinuxPerfImporter);
913
914 return {
915 LinuxPerfImporter: LinuxPerfImporter,
916 _LinuxPerfImporterTestExports: TestExports
917 };
918
919 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698