summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/trace-viewer/src/tracing/importer/linux_perf_importer.js
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/trace-viewer/src/tracing/importer/linux_perf_importer.js')
-rw-r--r--chromium/third_party/trace-viewer/src/tracing/importer/linux_perf_importer.js797
1 files changed, 0 insertions, 797 deletions
diff --git a/chromium/third_party/trace-viewer/src/tracing/importer/linux_perf_importer.js b/chromium/third_party/trace-viewer/src/tracing/importer/linux_perf_importer.js
deleted file mode 100644
index 7888642e1b5..00000000000
--- a/chromium/third_party/trace-viewer/src/tracing/importer/linux_perf_importer.js
+++ /dev/null
@@ -1,797 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Imports text files in the Linux event trace format into the
- * Tracemodel. This format is output both by sched_trace and by Linux's perf
- * tool.
- *
- * This importer assumes the events arrive as a string. The unit tests provide
- * examples of the trace format.
- *
- * Linux scheduler traces use a definition for 'pid' that is different than
- * tracing uses. Whereas tracing uses pid to identify a specific process, a pid
- * in a linux trace refers to a specific thread within a process. Within this
- * file, we the definition used in Linux traces, as it improves the importing
- * code's readability.
- */
-'use strict';
-
-base.require('tracing.trace_model');
-base.require('tracing.color_scheme');
-base.require('tracing.importer.importer');
-base.require('tracing.importer.linux_perf.bus_parser');
-base.require('tracing.importer.linux_perf.clock_parser');
-base.require('tracing.importer.linux_perf.cpufreq_parser');
-base.require('tracing.importer.linux_perf.disk_parser');
-base.require('tracing.importer.linux_perf.drm_parser');
-base.require('tracing.importer.linux_perf.exynos_parser');
-base.require('tracing.importer.linux_perf.gesture_parser');
-base.require('tracing.importer.linux_perf.i915_parser');
-base.require('tracing.importer.linux_perf.mali_parser');
-base.require('tracing.importer.linux_perf.power_parser');
-base.require('tracing.importer.linux_perf.sched_parser');
-base.require('tracing.importer.linux_perf.sync_parser');
-base.require('tracing.importer.linux_perf.workqueue_parser');
-base.require('tracing.importer.linux_perf.android_parser');
-base.require('tracing.importer.linux_perf.kfunc_parser');
-
-base.exportTo('tracing.importer', function() {
-
- var Importer = tracing.importer.Importer;
-
- /**
- * Represents the scheduling state for a single thread.
- * @constructor
- */
- function CpuState(cpu) {
- this.cpu = cpu;
- }
-
- CpuState.prototype = {
- __proto__: Object.prototype,
-
- /**
- * Switches the active pid on this Cpu. If necessary, add a Slice
- * to the cpu representing the time spent on that Cpu since the last call to
- * switchRunningLinuxPid.
- */
- switchRunningLinuxPid: function(importer, prevState, ts, pid, comm, prio) {
- // Generate a slice if the last active pid was not the idle task
- if (this.lastActivePid !== undefined && this.lastActivePid != 0) {
- var duration = ts - this.lastActiveTs;
- var thread = importer.threadsByLinuxPid[this.lastActivePid];
- var name;
- if (thread)
- name = thread.userFriendlyName;
- else
- name = this.lastActiveComm;
-
- var slice = new tracing.trace_model.CpuSlice(
- '', name,
- tracing.getStringColorId(name),
- this.lastActiveTs,
- {
- comm: this.lastActiveComm,
- tid: this.lastActivePid,
- prio: this.lastActivePrio,
- stateWhenDescheduled: prevState
- },
- duration);
- slice.cpu = this.cpu;
- this.cpu.slices.push(slice);
- }
-
- this.lastActiveTs = ts;
- this.lastActivePid = pid;
- this.lastActiveComm = comm;
- this.lastActivePrio = prio;
- }
- };
-
- /**
- * Imports linux perf events into a specified model.
- * @constructor
- */
- function LinuxPerfImporter(model, events) {
- this.importPriority = 2;
- this.model_ = model;
- this.events_ = events;
- this.clockSyncRecords_ = [];
- this.cpuStates_ = {};
- this.wakeups_ = [];
- this.kernelThreadStates_ = {};
- this.buildMapFromLinuxPidsToThreads();
- this.lines_ = [];
- this.pseudoThreadCounter = 1;
- this.parsers_ = [];
- this.eventHandlers_ = {};
- }
-
- var TestExports = {};
-
- // Matches the trace record in 3.2 and later with the print-tgid option:
- // <idle>-0 0 [001] d... 1.23: sched_switch
- //
- // A TGID (Thread Group ID) is basically what the Linux kernel calls what
- // userland refers to as a process ID (as opposed to a Linux pid, which is
- // what userland calls a thread ID).
- var lineREWithTGID = new RegExp(
- '^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]' +
- '\\s+[dX.][N.][Hhs.][0-9a-f.]' +
- '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');
- var lineParserWithTGID = function(line) {
- var groups = lineREWithTGID.exec(line);
- if (!groups) {
- return groups;
- }
-
- var tgid = groups[3];
- if (tgid[0] === '-')
- tgid = undefined;
-
- return {
- threadName: groups[1],
- pid: groups[2],
- tgid: tgid,
- cpuNumber: groups[4],
- timestamp: groups[5],
- eventName: groups[6],
- details: groups[7]
- };
- };
- TestExports.lineParserWithTGID = lineParserWithTGID;
-
- // Matches the default trace record in 3.2 and later (includes irq-info):
- // <idle>-0 [001] d... 1.23: sched_switch
- var lineREWithIRQInfo = new RegExp(
- '^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]' +
- '\\s+[dX.][N.][Hhs.][0-9a-f.]' +
- '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');
- var lineParserWithIRQInfo = function(line) {
- var groups = lineREWithIRQInfo.exec(line);
- if (!groups) {
- return groups;
- }
- return {
- threadName: groups[1],
- pid: groups[2],
- cpuNumber: groups[3],
- timestamp: groups[4],
- eventName: groups[5],
- details: groups[6]
- };
- };
- TestExports.lineParserWithIRQInfo = lineParserWithIRQInfo;
-
- // Matches the default trace record pre-3.2:
- // <idle>-0 [001] 1.23: sched_switch
- var lineREWithLegacyFmt =
- /^\s*(.+)-(\d+)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;
- var lineParserWithLegacyFmt = function(line) {
- var groups = lineREWithLegacyFmt.exec(line);
- if (!groups) {
- return groups;
- }
- return {
- threadName: groups[1],
- pid: groups[2],
- cpuNumber: groups[3],
- timestamp: groups[4],
- eventName: groups[5],
- details: groups[6]
- };
- };
- TestExports.lineParserWithLegacyFmt = lineParserWithLegacyFmt;
-
- // Matches the trace_event_clock_sync record
- // 0: trace_event_clock_sync: parent_ts=19581477508
- var traceEventClockSyncRE = /trace_event_clock_sync: parent_ts=(\d+\.?\d*)/;
- TestExports.traceEventClockSyncRE = traceEventClockSyncRE;
-
- // Some kernel trace events are manually classified in slices and
- // hand-assigned a pseudo PID.
- var pseudoKernelPID = 0;
-
- /**
- * Deduce the format of trace data. Linix kernels prior to 3.3 used one
- * format (by default); 3.4 and later used another. Additionally, newer
- * kernels can optionally trace the TGID.
- *
- * @return {function} the function for parsing data when the format is
- * recognized; otherwise null.
- */
- function autoDetectLineParser(line) {
- if (line[0] == '{')
- return false;
- if (lineREWithTGID.test(line))
- return lineParserWithTGID;
- if (lineREWithIRQInfo.test(line))
- return lineParserWithIRQInfo;
- if (lineREWithLegacyFmt.test(line))
- return lineParserWithLegacyFmt;
- return null;
- };
- TestExports.autoDetectLineParser = autoDetectLineParser;
-
- /**
- * Guesses whether the provided events is a Linux perf string.
- * Looks for the magic string "# tracer" at the start of the file,
- * or the typical task-pid-cpu-timestamp-function sequence of a typical
- * trace's body.
- *
- * @return {boolean} True when events is a linux perf array.
- */
- LinuxPerfImporter.canImport = function(events) {
- if (!(typeof(events) === 'string' || events instanceof String))
- return false;
-
- if (LinuxPerfImporter._extractEventsFromSystraceHTML(events, false).ok)
- return true;
-
- if (/^# tracer:/.test(events))
- return true;
-
- var m = /^(.+)\n/.exec(events);
- if (m)
- events = m[1];
- if (autoDetectLineParser(events))
- return true;
-
- return false;
- };
-
- LinuxPerfImporter._extractEventsFromSystraceHTML = function(
- incoming_events, produce_result) {
- var failure = {ok: false};
- if (produce_result === undefined)
- produce_result = true;
-
- if (/^<!DOCTYPE HTML>/.test(incoming_events) == false)
- return failure;
- var lines = incoming_events.split('\n');
- var cur_line = 1;
- function advanceToLineMatching(regex) {
- for (; cur_line < lines.length; cur_line++) {
- if (regex.test(lines[cur_line]))
- return true;
- }
- return false;
- }
-
- // Try to find the data...
- if (!advanceToLineMatching(/^ <script>$/))
- return failure;
- if (!advanceToLineMatching(/^ var linuxPerfData = "\\$/))
- return failure;
- var events_begin_at_line = cur_line + 1;
-
- if (!advanceToLineMatching(/^ <\/script>$/))
- return failure;
- var events_end_at_line = cur_line;
-
- if (!advanceToLineMatching(/^<\/body>$/))
- return failure;
- if (!advanceToLineMatching(/^<\/html>$/))
- return failure;
-
- var raw_events = lines.slice(events_begin_at_line,
- events_end_at_line);
- function endsWith(str, suffix) {
- return str.indexOf(suffix, str.length - suffix.length) !== -1;
- }
- function stripSuffix(str, suffix) {
- if (!endsWith(str, suffix))
- return str;
- return str.substring(str, str.length - suffix.length);
- }
-
- // Strip off escaping in the file needed to preserve linebreaks.
- var events = [];
- if (produce_result) {
- for (var i = 0; i < raw_events.length; i++) {
- var event = raw_events[i];
- event = stripSuffix(event, '\\n\\');
- events.push(event);
- }
- } else {
- events = [raw_events[raw_events.length - 1]];
- }
-
- // Last event ends differently. Strip that off too,
- // treating absence of that trailing stirng as a failure.
- var oldLastEvent = events[events.length - 1];
- var newLastEvent = stripSuffix(oldLastEvent, '\\n";');
- if (newLastEvent == oldLastEvent)
- return failure;
- events[events.length - 1] = newLastEvent;
-
- return {ok: true,
- lines: produce_result ? events : undefined,
- events_begin_at_line: events_begin_at_line};
- };
-
- LinuxPerfImporter.prototype = {
- __proto__: Importer.prototype,
-
- get model() {
- return this.model_;
- },
-
- /**
- * Precomputes a lookup table from linux pids back to existing
- * Threads. This is used during importing to add information to each
- * thread about whether it was running, descheduled, sleeping, et
- * cetera.
- */
- buildMapFromLinuxPidsToThreads: function() {
- this.threadsByLinuxPid = {};
- this.model_.getAllThreads().forEach(
- function(thread) {
- this.threadsByLinuxPid[thread.tid] = thread;
- }.bind(this));
- },
-
- /**
- * @return {CpuState} A CpuState corresponding to the given cpuNumber.
- */
- getOrCreateCpuState: function(cpuNumber) {
- if (!this.cpuStates_[cpuNumber]) {
- var cpu = this.model_.kernel.getOrCreateCpu(cpuNumber);
- this.cpuStates_[cpuNumber] = new CpuState(cpu);
- }
- return this.cpuStates_[cpuNumber];
- },
-
- /**
- * @return {TimelinThread} A thread corresponding to the kernelThreadName.
- */
- getOrCreateKernelThread: function(kernelThreadName, pid, tid) {
- if (!this.kernelThreadStates_[kernelThreadName]) {
- var thread = this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);
- thread.name = kernelThreadName;
- this.kernelThreadStates_[kernelThreadName] = {
- pid: pid,
- thread: thread,
- openSlice: undefined,
- openSliceTS: undefined
- };
- this.threadsByLinuxPid[pid] = thread;
- }
- return this.kernelThreadStates_[kernelThreadName];
- },
-
- /**
- * @return {TimelinThread} A pseudo thread corresponding to the
- * threadName. Pseudo threads are for events that we want to break
- * out to a separate timeline but would not otherwise happen.
- * These threads are assigned to pseudoKernelPID and given a
- * unique (incrementing) TID.
- */
- getOrCreatePseudoThread: function(threadName) {
- var thread = this.kernelThreadStates_[threadName];
- if (!thread) {
- thread = this.getOrCreateKernelThread(threadName, pseudoKernelPID,
- this.pseudoThreadCounter);
- this.pseudoThreadCounter++;
- }
- return thread;
- },
-
- /**
- * Imports the data in this.events_ into model_.
- */
- importEvents: function(isSecondaryImport) {
- this.createParsers();
- this.parseLines();
- this.importClockSyncRecords();
- var timeShift = this.computeTimeTransform(isSecondaryImport);
- if (timeShift === undefined) {
- this.model_.importWarning({
- type: 'clock_sync',
- message: 'Cannot import kernel trace without a clock sync.'
- });
- return;
- }
- this.importCpuData(timeShift);
- this.buildMapFromLinuxPidsToThreads();
- this.buildPerThreadCpuSlicesFromCpuState();
- },
-
- /**
- * Builds the timeSlices array on each thread based on our knowledge of what
- * each Cpu is doing. This is done only for Threads that are
- * already in the model, on the assumption that not having any traced data
- * on a thread means that it is not of interest to the user.
- */
- buildPerThreadCpuSlicesFromCpuState: function() {
- // Push the cpu slices to the threads that they run on.
- for (var cpuNumber in this.cpuStates_) {
- var cpuState = this.cpuStates_[cpuNumber];
- var cpu = cpuState.cpu;
-
- for (var i = 0; i < cpu.slices.length; i++) {
- var cpuSlice = cpu.slices[i];
-
- var thread = this.threadsByLinuxPid[cpuSlice.args.tid];
- if (!thread)
- continue;
-
- cpuSlice.threadThatWasRunning = thread;
-
- if (!thread.tempCpuSlices)
- thread.tempCpuSlices = [];
- thread.tempCpuSlices.push(cpuSlice);
- }
- }
-
- for (var i in this.wakeups_) {
- var wakeup = this.wakeups_[i];
- var thread = this.threadsByLinuxPid[wakeup.tid];
- if (!thread)
- continue;
- thread.tempWakeups = thread.tempWakeups || [];
- thread.tempWakeups.push(wakeup);
- }
-
- // Create slices for when the thread is not running.
- var runningId = tracing.getColorIdByName('running');
- var runnableId = tracing.getColorIdByName('runnable');
- var sleepingId = tracing.getColorIdByName('sleeping');
- var ioWaitId = tracing.getColorIdByName('iowait');
- this.model_.getAllThreads().forEach(function(thread) {
- if (thread.tempCpuSlices === undefined)
- return;
- var origSlices = thread.tempCpuSlices;
- delete thread.tempCpuSlices;
-
- origSlices.sort(function(x, y) {
- return x.start - y.start;
- });
-
- var wakeups = thread.tempWakeups || [];
- delete thread.tempWakeups;
- wakeups.sort(function(x, y) {
- return x.ts - y.ts;
- });
-
- // Walk the slice list and put slices between each original slice to
- // show when the thread isn't running.
- var slices = [];
-
- if (origSlices.length) {
- var slice = origSlices[0];
-
- if (wakeups.length && wakeups[0].ts < slice.start) {
- var wakeup = wakeups.shift();
- var wakeupDuration = slice.start - wakeup.ts;
- var args = {'wakeup from tid': wakeup.fromTid};
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Runnable', runnableId,
- wakeup.ts, args, wakeupDuration));
- }
-
- var runningSlice = new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Running', runningId,
- slice.start, {}, slice.duration);
- runningSlice.cpuOnWhichThreadWasRunning = slice.cpu;
- slices.push(runningSlice);
- }
-
- var wakeup = undefined;
- for (var i = 1; i < origSlices.length; i++) {
- var prevSlice = origSlices[i - 1];
- var nextSlice = origSlices[i];
- var midDuration = nextSlice.start - prevSlice.end;
- while (wakeups.length && wakeups[0].ts < nextSlice.start) {
- var w = wakeups.shift();
- if (wakeup === undefined && w.ts > prevSlice.end) {
- wakeup = w;
- }
- }
-
- // Push a sleep slice onto the slices list, interrupting it with a
- // wakeup if appropriate.
- var pushSleep = function(title, id) {
- if (wakeup !== undefined) {
- midDuration = wakeup.ts - prevSlice.end;
- }
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread,
- '', title, id, prevSlice.end, {}, midDuration));
- if (wakeup !== undefined) {
- var wakeupDuration = nextSlice.start - wakeup.ts;
- var args = {'wakeup from tid': wakeup.fromTid};
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread,
- '', 'Runnable', runnableId, wakeup.ts, args, wakeupDuration));
- wakeup = undefined;
- }
- };
-
- if (prevSlice.args.stateWhenDescheduled == 'S') {
- pushSleep('Sleeping', sleepingId);
- } else if (prevSlice.args.stateWhenDescheduled == 'R' ||
- prevSlice.args.stateWhenDescheduled == 'R+') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread,
- '', 'Runnable', runnableId, prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'D') {
- pushSleep('Uninterruptible Sleep', ioWaitId);
- } else if (prevSlice.args.stateWhenDescheduled == 'T') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', '__TASK_STOPPED', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 't') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'debug', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'Z') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Zombie', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'X') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Exit Dead', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'x') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Task Dead', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'K') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Wakekill', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'W') {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Waking', ioWaitId,
- prevSlice.end, {}, midDuration));
- } else if (prevSlice.args.stateWhenDescheduled == 'D|K') {
- pushSleep('Uninterruptible Sleep | WakeKill', ioWaitId);
- } else if (prevSlice.args.stateWhenDescheduled == 'D|W') {
- pushSleep('Uninterruptible Sleep | Waking', ioWaitId);
- } else {
- slices.push(new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'UNKNOWN', ioWaitId,
- prevSlice.end, {}, midDuration));
- this.model_.importWarning({
- type: 'parse_error',
- message: 'Unrecognized sleep state: ' +
- prevSlice.args.stateWhenDescheduled
- });
- }
-
- var runningSlice = new tracing.trace_model.ThreadTimeSlice(
- thread, '', 'Running', runningId,
- nextSlice.start, {}, nextSlice.duration);
- runningSlice.cpuOnWhichThreadWasRunning = prevSlice.cpu;
- slices.push(runningSlice);
- }
- thread.timeSlices = slices;
- }, this);
- },
-
- /**
- * Computes a time transform from perf time to parent time based on the
- * imported clock sync records.
- * @return {number} offset from perf time to parent time or undefined if
- * the necessary sync records were not found.
- */
- computeTimeTransform: function(isSecondaryImport) {
- // If this is a secondary import, and no clock syncing records were
- // found, then abort the import. Otherwise, just skip clock alignment.
- if (this.clockSyncRecords_.length == 0)
- return isSecondaryImport ? undefined : 0;
-
- // Shift all the slice times based on the sync record.
- // TODO(skyostil): Compute a scaling factor if we have multiple clock sync
- // records.
- var sync = this.clockSyncRecords_[0];
- // NB: parentTS of zero denotes no times-shift; this is
- // used when user and kernel event clocks are identical.
- if (sync.parentTS == 0 || sync.parentTS == sync.perfTS)
- return 0;
- return sync.parentTS - sync.perfTS;
- },
-
- /**
- * Creates an instance of each registered linux perf event parser.
- * This allows the parsers to register handlers for the events they
- * understand. We also register our own special handlers (for the
- * timestamp synchronization markers).
- */
- createParsers: function() {
- // Instantiate the parsers; this will register handlers for known events
- var parserConstructors =
- tracing.importer.linux_perf.Parser.getSubtypeConstructors();
- for (var i = 0; i < parserConstructors.length; ++i) {
- var parserConstructor = parserConstructors[i];
- this.parsers_.push(new parserConstructor(this));
- }
-
- this.registerEventHandler('tracing_mark_write',
- LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));
- // NB: old-style trace markers; deprecated
- this.registerEventHandler('0',
- LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));
- // Register dummy clock sync handlers to avoid warnings in the log.
- this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',
- function() { return true; });
- this.registerEventHandler('0:trace_event_clock_sync',
- function() { return true; });
- },
-
- /**
- * Registers a linux perf event parser used by importCpuData.
- */
- registerEventHandler: function(eventName, handler) {
- // TODO(sleffler) how to handle conflicts?
- this.eventHandlers_[eventName] = handler;
- },
-
- /**
- * Records the fact that a pid has become runnable. This data will
- * eventually get used to derive each thread's timeSlices array.
- */
- markPidRunnable: function(ts, pid, comm, prio, fromPid) {
- // The the pids that get passed in to this function are Linux kernel
- // pids, which identify threads. The rest of trace-viewer refers to
- // these as tids, so the change of nomenclature happens in the following
- // construction of the wakeup object.
- this.wakeups_.push({ts: ts, tid: pid, fromTid: fromPid});
- },
-
- /**
- * Processes a trace_event_clock_sync event.
- */
- traceClockSyncEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
- var event = /parent_ts=(\d+\.?\d*)/.exec(eventBase.details);
- if (!event)
- return false;
-
- this.clockSyncRecords_.push({
- perfTS: ts,
- parentTS: event[1] * 1000
- });
- return true;
- },
-
- /**
- * Processes a trace_marking_write event.
- */
- traceMarkingWriteEvent: function(eventName, cpuNumber, pid, ts, eventBase,
- threadName) {
- var event = /^\s*(\w+):\s*(.*)$/.exec(eventBase.details);
- if (!event) {
- // Check if the event matches events traced by the Android framework
- var tag = eventBase.details.substring(0, 2);
- if (tag == 'B|' || tag == 'E' || tag == 'E|' || tag == 'X|' ||
- tag == 'C|' || tag == 'S|' || tag == 'F|') {
- eventBase.subEventName = 'android';
- } else {
- return false;
- }
- } else {
- eventBase.subEventName = event[1];
- eventBase.details = event[2];
- }
-
- var writeEventName = eventName + ':' + eventBase.subEventName;
- var handler = this.eventHandlers_[writeEventName];
- if (!handler) {
- this.model_.importWarning({
- type: 'parse_error',
- message: 'Unknown trace_marking_write event ' + writeEventName
- });
- return true;
- }
- return handler(writeEventName, cpuNumber, pid, ts, eventBase, threadName);
- },
-
- /**
- * Populates this.clockSyncRecords_ with found clock sync markers.
- */
- importClockSyncRecords: function() {
- this.forEachLine(function(text, eventBase, cpuNumber, pid, ts) {
- var eventName = eventBase.eventName;
- if ((eventName !== 'tracing_mark_write' && eventName !== '0') ||
- !traceEventClockSyncRE.exec(eventBase.details))
- return;
- this.traceClockSyncEvent(eventName, cpuNumber, pid, ts, eventBase);
- }.bind(this));
- },
-
- /**
- * Walks the this.events_ structure and creates Cpu objects.
- */
- importCpuData: function(timeShift) {
- this.forEachLine(function(text, eventBase, cpuNumber, pid, ts) {
- var eventName = eventBase.eventName;
- var handler = this.eventHandlers_[eventName];
- if (!handler) {
- this.model_.importWarning({
- type: 'parse_error',
- message: 'Unknown event ' + eventName + ' (' + text + ')'
- });
- return;
- }
- ts += timeShift;
- if (!handler(eventName, cpuNumber, pid, ts, eventBase)) {
- this.model_.importWarning({
- type: 'parse_error',
- message: 'Malformed ' + eventName + ' event (' + text + ')'
- });
- }
- }.bind(this));
- },
-
- /**
- * Walks the this.events_ structure and populates this.lines_.
- */
- parseLines: function() {
- var extractResult = LinuxPerfImporter._extractEventsFromSystraceHTML(
- this.events_, true);
- var lineNumberBase = 0;
- var lines;
- if (extractResult.ok) {
- lineNumberBase = extractResult.events_begin_at_line;
- lines = extractResult.lines;
- } else
- lines = this.events_.split('\n');
-
- var lineParser = null;
- for (var lineNumber = lineNumberBase;
- lineNumber < lines.length;
- ++lineNumber) {
- var line = lines[lineNumber];
- if (line.length == 0 || /^#/.test(line))
- continue;
- if (lineParser == null) {
- lineParser = autoDetectLineParser(line);
- if (lineParser == null) {
- this.model_.importWarning({
- type: 'parse_error',
- message: 'Cannot parse line: ' + line
- });
- continue;
- }
- }
- var eventBase = lineParser(line);
- if (!eventBase) {
- this.model_.importWarning({
- type: 'parse_error',
- message: 'Unrecognized line: ' + line
- });
- continue;
- }
-
- this.lines_.push([
- line,
- eventBase,
- parseInt(eventBase.cpuNumber),
- parseInt(eventBase.pid),
- parseFloat(eventBase.timestamp) * 1000
- ]);
- }
- },
-
- /**
- * Calls |handler| for every parsed line.
- */
- forEachLine: function(handler) {
- for (var i = 0; i < this.lines_.length; ++i) {
- var line = this.lines_[i];
- handler.apply(this, line);
- }
- }
- };
-
- tracing.TraceModel.registerImporter(LinuxPerfImporter);
-
- return {
- LinuxPerfImporter: LinuxPerfImporter,
- _LinuxPerfImporterTestExports: TestExports
- };
-
-});