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); |
} |
}; |