| Index: tracing/tracing/extras/importer/trace_event_importer.html
|
| diff --git a/tracing/tracing/extras/importer/trace_event_importer.html b/tracing/tracing/extras/importer/trace_event_importer.html
|
| index 2c1392d020a5466385f6772fe2961a27283ccc8e..0487e8f80f439d1fb5a92b5bb4888a6bea57d772 100644
|
| --- a/tracing/tracing/extras/importer/trace_event_importer.html
|
| +++ b/tracing/tracing/extras/importer/trace_event_importer.html
|
| @@ -54,8 +54,6 @@ tr.exportTo('tr.e.importer', function() {
|
| }
|
| }
|
|
|
| - var timestampFromUs = tr.b.Unit.timestampFromUs;
|
| -
|
| var PRODUCER = 'producer';
|
| var CONSUMER = 'consumer';
|
| var STEP = 'step';
|
| @@ -68,6 +66,8 @@ tr.exportTo('tr.e.importer', function() {
|
|
|
| var GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX = 'global/';
|
|
|
| + var ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX = 'ClockSyncEvent.';
|
| +
|
| // Map from raw memory dump byte stat names to model byte stat names. See
|
| // //base/trace_event/process_memory_maps.cc in Chromium.
|
| var BYTE_STAT_NAME_MAP = {
|
| @@ -132,6 +132,7 @@ tr.exportTo('tr.e.importer', function() {
|
| this.eventsWereFromString_ = false;
|
| this.softwareMeasuredCpuCount_ = undefined;
|
|
|
| +
|
| this.allAsyncEvents_ = [];
|
| this.allFlowEvents_ = [];
|
| this.allObjectEvents_ = [];
|
| @@ -144,6 +145,11 @@ tr.exportTo('tr.e.importer', function() {
|
| this.v8ProcessRootStackFrame_ = {};
|
| this.v8SamplingData_ = [];
|
|
|
| + // For tracking async events that is used to create back-compat clock sync
|
| + // event.
|
| + this.asyncClockSyncStart_ = undefined;
|
| + this.asyncClockSyncFinish_ = undefined;
|
| +
|
| // Dump ID -> PID -> [process memory dump events].
|
| this.allMemoryDumpEvents_ = {};
|
|
|
| @@ -153,6 +159,9 @@ tr.exportTo('tr.e.importer', function() {
|
| // For old Chrome traces with no clock domain metadata, just use a
|
| // placeholder clock domain.
|
| this.clockDomainId_ = tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;
|
| + // A function able to transform timestamps in |clockDomainId| to timestamps
|
| + // in the model clock domain.
|
| + this.toModelTime_ = undefined;
|
|
|
| if (typeof(eventData) === 'string' || eventData instanceof String) {
|
| eventData = eventData.trim();
|
| @@ -350,7 +359,7 @@ tr.exportTo('tr.e.importer', function() {
|
| }
|
| }
|
|
|
| - var ts = timestampFromUs(event.ts);
|
| + var ts = this.toModelTimeFromUs_(event.ts);
|
| ctr.series.forEach(function(series) {
|
| var val = event.args[series.name] ? event.args[series.name] : 0;
|
| series.addCounterSample(ts, val);
|
| @@ -415,7 +424,7 @@ tr.exportTo('tr.e.importer', function() {
|
| processDurationEvent: function(event) {
|
| var thread = this.model_.getOrCreateProcess(event.pid)
|
| .getOrCreateThread(event.tid);
|
| - var ts = timestampFromUs(event.ts);
|
| + var ts = this.toModelTimeFromUs_(event.ts);
|
| if (!thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)) {
|
| this.model_.importWarning({
|
| type: 'duration_parse_error',
|
| @@ -426,9 +435,9 @@ tr.exportTo('tr.e.importer', function() {
|
|
|
| if (event.ph === 'B') {
|
| var slice = thread.sliceGroup.beginSlice(
|
| - event.cat, event.name, timestampFromUs(event.ts),
|
| + event.cat, event.name, this.toModelTimeFromUs_(event.ts),
|
| this.deepCopyIfNeeded_(event.args),
|
| - timestampFromUs(event.tts), event.argsStripped,
|
| + this.toModelTimeFromUs_(event.tts), event.argsStripped,
|
| getEventColor(event));
|
| slice.startStackFrame = this.getStackFrameForEvent_(event);
|
| this.setContextsFromThread_(thread, slice);
|
| @@ -437,13 +446,14 @@ tr.exportTo('tr.e.importer', function() {
|
| throw new Error('This should never happen');
|
|
|
| thread.sliceGroup.beginSlice(event.cat, event.name,
|
| - timestampFromUs(event.ts),
|
| + this.toModelTimeFromUs_(event.ts),
|
| this.deepCopyIfNeeded_(event.args),
|
| - timestampFromUs(event.tts),
|
| + this.toModelTimeFromUs_(event.tts),
|
| event.argsStripped,
|
| getEventColor(event));
|
| - var slice = thread.sliceGroup.endSlice(timestampFromUs(event.ts),
|
| - timestampFromUs(event.tts));
|
| + var slice = thread.sliceGroup.endSlice(
|
| + this.toModelTimeFromUs_(event.ts),
|
| + this.toModelTimeFromUs_(event.tts));
|
| slice.startStackFrame = this.getStackFrameForEvent_(event);
|
| slice.endStackFrame = undefined;
|
| } else {
|
| @@ -455,9 +465,10 @@ tr.exportTo('tr.e.importer', function() {
|
| return;
|
| }
|
|
|
| - var slice = thread.sliceGroup.endSlice(timestampFromUs(event.ts),
|
| - timestampFromUs(event.tts),
|
| - getEventColor(event));
|
| + var slice = thread.sliceGroup.endSlice(
|
| + this.toModelTimeFromUs_(event.ts),
|
| + this.toModelTimeFromUs_(event.tts),
|
| + getEventColor(event));
|
| if (event.name && slice.title != event.name) {
|
| this.model_.importWarning({
|
| type: 'title_match_error',
|
| @@ -507,10 +518,11 @@ tr.exportTo('tr.e.importer', function() {
|
| }
|
|
|
| var slice = thread.sliceGroup.pushCompleteSlice(event.cat, event.name,
|
| - timestampFromUs(event.ts),
|
| - timestampFromUs(event.dur),
|
| - timestampFromUs(event.tts),
|
| - timestampFromUs(event.tdur),
|
| +
|
| + this.toModelTimeFromUs_(event.ts),
|
| + this.maybeToModelTimeFromUs_(event.dur),
|
| + this.maybeToModelTimeFromUs_(event.tts),
|
| + this.maybeToModelTimeFromUs_(event.tdur),
|
| this.deepCopyIfNeeded_(event.args),
|
| event.argsStripped,
|
| getEventColor(event),
|
| @@ -640,7 +652,7 @@ tr.exportTo('tr.e.importer', function() {
|
| }
|
|
|
| var instantEvent = new constructor(event.cat, event.name,
|
| - getEventColor(event), timestampFromUs(event.ts),
|
| + getEventColor(event), this.toModelTimeFromUs_(event.ts),
|
| this.deepCopyIfNeeded_(event.args));
|
|
|
| switch (instantEvent.type) {
|
| @@ -736,7 +748,7 @@ tr.exportTo('tr.e.importer', function() {
|
|
|
| var sample = new tr.model.Sample(
|
| undefined /* cpu */, thread, 'V8 Sample',
|
| - timestampFromUs(event.ts), lastStackFrame, 1 /* weight */,
|
| + this.toModelTimeFromUs_(event.ts), lastStackFrame, 1 /* weight */,
|
| this.deepCopyIfNeeded_(event.args));
|
| this.model_.samples.push(sample);
|
| },
|
| @@ -766,7 +778,7 @@ tr.exportTo('tr.e.importer', function() {
|
|
|
| var sample = new tr.model.Sample(
|
| undefined, thread, 'Trace Event Sample',
|
| - timestampFromUs(event.ts), stackFrame, 1,
|
| + this.toModelTimeFromUs_(event.ts), stackFrame, 1,
|
| this.deepCopyIfNeeded_(event.args));
|
| this.setContextsFromThread_(thread, sample);
|
| this.model_.samples.push(sample);
|
| @@ -839,8 +851,9 @@ tr.exportTo('tr.e.importer', function() {
|
| // ...
|
| // }
|
| this.model_.clockSyncManager.addClockSyncMarker(
|
| - this.clockDomainId_, syncId, timestampFromUs(event.args.issue_ts),
|
| - timestampFromUs(event.ts));
|
| + this.clockDomainId_, syncId,
|
| + tr.b.Unit.timestampFromUs(event.args.issue_ts),
|
| + tr.b.Unit.timestampFromUs(event.ts));
|
| } else {
|
| // When Chrome is a tracing agent and is the recipient of the clock
|
| // sync request, the clock sync event looks like:
|
| @@ -852,7 +865,7 @@ tr.exportTo('tr.e.importer', function() {
|
| // ...
|
| // }
|
| this.model_.clockSyncManager.addClockSyncMarker(
|
| - this.clockDomainId_, syncId, timestampFromUs(event.ts));
|
| + this.clockDomainId_, syncId, tr.b.Unit.timestampFromUs(event.ts));
|
| }
|
| },
|
|
|
| @@ -879,10 +892,57 @@ tr.exportTo('tr.e.importer', function() {
|
| }
|
| },
|
|
|
| + initBackcompatClockSyncEventTracker_: function(event) {
|
| + if (event.name !== undefined &&
|
| + event.name.startsWith(ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX) &&
|
| + event.ph === 'S')
|
| + this.asyncClockSyncStart_ = event;
|
| +
|
| + if (event.name !== undefined &&
|
| + event.name.startsWith(ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX) &&
|
| + event.ph === 'F')
|
| + this.asyncClockSyncFinish_ = event;
|
| + if (this.asyncClockSyncStart_ == undefined ||
|
| + this.asyncClockSyncFinish_ == undefined)
|
| + return;
|
| +
|
| + // Older version of Chrome doesn't support clock sync API, hence
|
| + // telemetry get around it by marking the clock sync events with
|
| + // console.time & console.timeEnd. When we encounter async events
|
| + // with named started with 'ClockSyncEvent.' prefix, create a
|
| + // synthetic clock sync events based on their timestamps.
|
| + var syncId =
|
| + this.asyncClockSyncStart_.name.substring(
|
| + ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX.length);
|
| + if (syncId !==
|
| + this.asyncClockSyncFinish_.name.substring(
|
| + ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX.length)) {
|
| + throw new Error('Inconsistent clock sync id of async clock sync ' +
|
| + 'events.');
|
| + }
|
| + var clockSyncEvent = {
|
| + ph: 'c',
|
| + args: {
|
| + sync_id: syncId,
|
| + issue_ts: this.asyncClockSyncStart_.ts
|
| + },
|
| + ts: this.asyncClockSyncFinish_.ts,
|
| + };
|
| + this.asyncClockSyncStart_ = undefined;
|
| + this.asyncClockSyncFinish_ = undefined;
|
| + return clockSyncEvent;
|
| + },
|
| +
|
| importClockSyncMarkers: function() {
|
| + var asyncClockSyncStart, asyncClockSyncFinish;
|
| for (var i = 0; i < this.events_.length; i++) {
|
| var event = this.events_[i];
|
|
|
| + var possibleBackCompatClockSyncEvent =
|
| + this.initBackcompatClockSyncEventTracker_(event);
|
| + if (possibleBackCompatClockSyncEvent)
|
| + this.processClockSyncEvent(possibleBackCompatClockSyncEvent);
|
| +
|
| if (event.ph !== 'c')
|
| continue;
|
|
|
| @@ -1216,7 +1276,7 @@ tr.exportTo('tr.e.importer', function() {
|
| var sample = new tr.model.Sample(
|
| cpu, thread,
|
| event.name,
|
| - timestampFromUs(event.ts),
|
| + this.toModelTimeFromUs_(event.ts),
|
| stackFrame,
|
| event.weight);
|
| m.samples.push(sample);
|
| @@ -1382,10 +1442,10 @@ tr.exportTo('tr.e.importer', function() {
|
| events[0].event.cat,
|
| name,
|
| getEventColor(events[0].event),
|
| - timestampFromUs(events[0].event.ts),
|
| + this.toModelTimeFromUs_(events[0].event.ts),
|
| tr.b.concatenateObjects(events[0].event.args,
|
| events[events.length - 1].event.args),
|
| - timestampFromUs(event.ts - events[0].event.ts),
|
| + this.toModelTimeFromUs_(event.ts - events[0].event.ts),
|
| true, undefined, undefined, events[0].event.argsStripped);
|
| slice.startThread = events[0].thread;
|
| slice.endThread = asyncEventState.thread;
|
| @@ -1439,9 +1499,9 @@ tr.exportTo('tr.e.importer', function() {
|
| events[0].event.cat,
|
| subName,
|
| getEventColor(event, subName + j),
|
| - timestampFromUs(events[startIndex].event.ts),
|
| + this.toModelTimeFromUs_(events[startIndex].event.ts),
|
| this.deepCopyIfNeeded_(events[j].event.args),
|
| - timestampFromUs(
|
| + this.toModelTimeFromUs_(
|
| events[endIndex].event.ts - events[startIndex].event.ts),
|
| undefined, undefined,
|
| events[startIndex].event.argsStripped);
|
| @@ -1569,9 +1629,9 @@ tr.exportTo('tr.e.importer', function() {
|
| var thread_start = undefined;
|
| var thread_duration = undefined;
|
| if (startState.event.tts && startState.event.use_async_tts) {
|
| - thread_start = timestampFromUs(startState.event.tts);
|
| + thread_start = this.toModelTimeFromUs_(startState.event.tts);
|
| if (endState.event.tts) {
|
| - var thread_end = timestampFromUs(endState.event.tts);
|
| + var thread_end = this.toModelTimeFromUs_(endState.event.tts);
|
| thread_duration = thread_end - thread_start;
|
| }
|
| }
|
| @@ -1580,9 +1640,9 @@ tr.exportTo('tr.e.importer', function() {
|
| eventStateEntry.event.cat,
|
| eventStateEntry.event.name,
|
| getEventColor(endState.event),
|
| - timestampFromUs(startState.event.ts),
|
| + this.toModelTimeFromUs_(startState.event.ts),
|
| sliceArgs,
|
| - timestampFromUs(endState.event.ts - startState.event.ts),
|
| + this.toModelTimeFromUs_(endState.event.ts - startState.event.ts),
|
| isTopLevel,
|
| thread_start,
|
| thread_duration,
|
| @@ -1668,17 +1728,17 @@ tr.exportTo('tr.e.importer', function() {
|
| return false;
|
| }
|
|
|
| - function createFlowEvent(thread, event, opt_slice) {
|
| + var createFlowEvent = function(thread, event, opt_slice) {
|
| var startSlice, flowId, flowStartTs;
|
|
|
| if (event.bind_id) {
|
| // Support Flow API v2.
|
| startSlice = opt_slice;
|
| flowId = event.bind_id;
|
| - flowStartTs = timestampFromUs(event.ts + event.dur);
|
| + flowStartTs = this.toModelTimeFromUs_(event.ts + event.dur);
|
| } else {
|
| // Support Flow API v1.
|
| - var ts = timestampFromUs(event.ts);
|
| + var ts = this.toModelTimeFromUs_(event.ts);
|
| startSlice = thread.sliceGroup.findSliceAtTs(ts);
|
| if (startSlice === undefined)
|
| return undefined;
|
| @@ -1698,10 +1758,10 @@ tr.exportTo('tr.e.importer', function() {
|
| flowEvent.endStackFrame = undefined;
|
| startSlice.outFlowEvents.push(flowEvent);
|
| return flowEvent;
|
| - }
|
| + }.bind(this);
|
|
|
| - function finishFlowEventWith(flowEvent, thread, event,
|
| - refGuid, bindToParent, opt_slice) {
|
| + var finishFlowEventWith = function(
|
| + flowEvent, thread, event, refGuid, bindToParent, opt_slice) {
|
| var endSlice;
|
|
|
| if (event.bind_id) {
|
| @@ -1709,7 +1769,7 @@ tr.exportTo('tr.e.importer', function() {
|
| endSlice = opt_slice;
|
| } else {
|
| // Support Flow API v1.
|
| - var ts = timestampFromUs(event.ts);
|
| + var ts = this.toModelTimeFromUs_(event.ts);
|
| if (bindToParent) {
|
| endSlice = thread.sliceGroup.findSliceAtTs(ts);
|
| } else {
|
| @@ -1721,14 +1781,15 @@ tr.exportTo('tr.e.importer', function() {
|
|
|
| endSlice.inFlowEvents.push(flowEvent);
|
| flowEvent.endSlice = endSlice;
|
| - flowEvent.duration = timestampFromUs(event.ts) - flowEvent.start;
|
| + flowEvent.duration =
|
| + this.toModelTimeFromUs_(event.ts) - flowEvent.start;
|
| flowEvent.endStackFrame = that.getStackFrameForEvent_(event);
|
| that.mergeArgsInto_(flowEvent.args, event.args, flowEvent.title);
|
| return true;
|
| - }
|
| + }.bind(this);
|
|
|
| - function processFlowConsumer(flowIdToEvent, sliceGuidToEvent, event,
|
| - slice) {
|
| + function processFlowConsumer(
|
| + flowIdToEvent, sliceGuidToEvent, event, slice) {
|
| var flowEvent = flowIdToEvent[event.bind_id];
|
| if (flowEvent === undefined) {
|
| that.model_.importWarning({
|
| @@ -1779,8 +1840,6 @@ tr.exportTo('tr.e.importer', function() {
|
| return false;
|
| }
|
| flowIdToEvent[event.bind_id] = flowEvent;
|
| -
|
| - return;
|
| }
|
|
|
| // Actual import.
|
| @@ -1911,7 +1970,7 @@ tr.exportTo('tr.e.importer', function() {
|
| if (this.allObjectEvents_.length === 0)
|
| return;
|
|
|
| - function processEvent(objectEventState) {
|
| + var processEvent = function(objectEventState) {
|
| var event = objectEventState.event;
|
| var scopedId = this.scopedIdForEvent_(event);
|
| var thread = objectEventState.thread;
|
| @@ -1931,7 +1990,7 @@ tr.exportTo('tr.e.importer', function() {
|
| });
|
| }
|
| var process = thread.parent;
|
| - var ts = timestampFromUs(event.ts);
|
| + var ts = this.toModelTimeFromUs_(event.ts);
|
| var instance;
|
| if (event.ph === 'N') {
|
| try {
|
| @@ -2001,7 +2060,7 @@ tr.exportTo('tr.e.importer', function() {
|
|
|
| if (instance)
|
| instance.colorId = getEventColor(event, instance.typeName);
|
| - }
|
| + }.bind(this);
|
|
|
| this.allObjectEvents_.sort(function(x, y) {
|
| var d = x.event.ts - y.event.ts;
|
| @@ -2159,7 +2218,7 @@ tr.exportTo('tr.e.importer', function() {
|
| for (var pid in dumpIdEvents) {
|
| var processEvents = dumpIdEvents[pid];
|
| for (var i = 0; i < processEvents.length; i++)
|
| - globalRange.addValue(timestampFromUs(processEvents[i].ts));
|
| + globalRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
|
| }
|
| if (globalRange.isEmpty)
|
| throw new Error('Internal error: Global memory dump without events');
|
| @@ -2209,7 +2268,7 @@ tr.exportTo('tr.e.importer', function() {
|
| // Calculate the range of the process memory dump.
|
| var processRange = new tr.b.Range();
|
| for (var i = 0; i < processEvents.length; i++)
|
| - processRange.addValue(timestampFromUs(processEvents[i].ts));
|
| + processRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
|
| if (processRange.isEmpty)
|
| throw new Error('Internal error: Process memory dump without events');
|
|
|
| @@ -2981,6 +3040,31 @@ tr.exportTo('tr.e.importer', function() {
|
| }
|
| }
|
| }
|
| + },
|
| +
|
| + /**
|
| + * Converts |ts| (in microseconds) to a timestamp in the model clock domain
|
| + * (in milliseconds).
|
| + */
|
| + toModelTimeFromUs_: function(ts) {
|
| + if (!this.toModelTime_) {
|
| + this.toModelTime_ =
|
| + this.model_.clockSyncManager.getModelTimeTransformer(
|
| + this.clockDomainId_);
|
| + }
|
| +
|
| + return this.toModelTime_(tr.b.Unit.timestampFromUs(ts));
|
| + },
|
| +
|
| + /**
|
| + * Converts |ts| (in microseconds) to a timestamp in the model clock domain
|
| + * (in milliseconds). If |ts| is undefined, undefined is returned.
|
| + */
|
| + maybeToModelTimeFromUs_: function(ts) {
|
| + if (ts === undefined)
|
| + return undefined;
|
| +
|
| + return this.toModelTimeFromUs_(ts);
|
| }
|
| };
|
|
|
|
|