Commit c635a663 authored by nduca@chromium.org's avatar nduca@chromium.org

Add TRACE_COUNTER support to about:tracing with dramatically improved test coverage.

Review URL: http://codereview.chromium.org/8513009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110671 0039d316-1c4b-4281-b951-d872f2087c98
parent 01172831
...@@ -46,10 +46,8 @@ cr.define('tracing', function() { ...@@ -46,10 +46,8 @@ cr.define('tracing', function() {
this.timelineView_ = new TimelineView(); this.timelineView_ = new TimelineView();
this.controlDiv_.appendChild(this.recordBn_); this.controlDiv_.appendChild(this.recordBn_);
if (!browserBridge.debugMode) { this.controlDiv_.appendChild(this.loadBn_);
this.controlDiv_.appendChild(this.loadBn_); this.controlDiv_.appendChild(this.saveBn_);
this.controlDiv_.appendChild(this.saveBn_);
}
this.container_.appendChild(this.timelineView_); this.container_.appendChild(this.timelineView_);
this.appendChild(this.container_); this.appendChild(this.container_);
......
// Copyright (c) 2011 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 Helper functions for use in tracing tests.
*/
cr.define('test_utils', function() {
function getJSON(url, cb) {
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.onreadystatechange = function(aEvt) {
if (req.readyState == 4) {
window.setTimeout(function() {
if (req.status == 200) {
var resp = JSON.parse(req.responseText);
if (resp.traceEvents)
cb(resp.traceEvents);
else
cb(resp);
} else {
console.log('Failed to load ' + url);
}
}, 0);
}
};
req.send(null);
}
return {
getJSON: getJSON
};
});
\ No newline at end of file
[
{"name": "a", "args": {},"pid": 52, "ts": 9524, "cat": "foo", "tid": 53,
"ph": "B"},
{"name": "a", "args": {},"pid": 52, "ts": 9560, "cat": "foo", "tid": 53,
"ph": "E"},
{"name": "b", "args": {},"pid": 52, "ts": 9629, "cat": "foo", "tid": 53,
"ph": "B"},
{"name": "b", "args": {},"pid": 52, "ts": 9631, "cat": "foo", "tid": 53,
"ph": "E"},
{"name": "counter", "args": {"value": 2}, "pid": 52, "ts": 9524,
"cat": "foo", "tid": 53, "ph": "C", "id": "123"},
{"name": "counter", "args": {"value": 10}, "pid": 52, "ts": 9626,
"cat": "foo", "tid": 53, "ph": "C", "id": "123"},
{"name": "counter", "args": {"value": 5}, "pid": 52, "ts": 9627,
"cat": "foo", "tid": 53, "ph": "C", "id": "123"},
{"name": "counter", "args": {"value": 8}, "pid": 52, "ts": 9628,
"cat": "foo", "tid": 53, "ph": "C", "id": "123"},
{"name": "counter", "args": {"value": 4}, "pid": 52, "ts": 9629,
"cat": "foo", "tid": 53, "ph": "C", "id": "123"},
{"name": "counter", "args": {"value": 10}, "pid": 52, "ts": 9631,
"cat": "foo", "tid": 53, "ph": "C", "id": "123"},
{"name": "counter", "args": {"value": 10}, "pid": 52, "ts": 9524,
"cat": "foo", "tid": 53, "ph": "C", "id": "b"},
{"name": "counter", "args": {"value": 0}, "pid": 52, "ts": 9631,
"cat": "foo", "tid": 53, "ph": "C", "id": "b"}
]
\ No newline at end of file
[
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 826, "ph": "B",
"name": "A", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 827, "ph": "B",
"name": "Asub", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 829, "ph": "B",
"name": "NonNest", "args": {"id": "1", "ui-nest": "0"}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 830, "ph": "B",
"name": "NonNest", "args": {"id": "2", "ui-nest": "0"}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 831, "ph": "E",
"name": "Asub", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 832, "ph": "E",
"name": "NonNest", "args": {"id": "1", "ui-nest": "0"}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 833, "ph": "E",
"name": "NonNest", "args": {"id": "2", "ui-nest": "0"}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 834, "ph": "E",
"name": "A", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22631, "ts": 827, "ph": "B",
"name": "A", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22631, "ts": 854, "ph": "E",
"name": "A", "args": {}}
]
\ No newline at end of file
[
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 826, "ph": "C",
"name": "counter", "args": {"value": 10}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 826, "ph": "B",
"name": "A long name that doesnt fit but is exceedingly informative",
"args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 827, "ph": "B",
"name": "Asub with a name that wont fit", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 828, "ph": "E",
"name": "Asub", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 829, "ph": "B",
"name": "Asub", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 832, "ph": "E",
"name": "Asub", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 832, "ph": "C",
"name": "counter", "args": {"value": 1}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 833, "ph": "E",
"name": "", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 835, "ph": "I",
"name": "I1", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 837, "ph": "I",
"name": "I2", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 839, "ph": "C",
"name": "counter", "args": {"value": 5}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 840, "ph": "B",
"name": "A not as long a name", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 848, "ph": "E",
"name": "A not as long a name", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 848, "ph": "C",
"name": "counter", "args": {"value": 1}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 854, "ph": "C",
"name": "counter", "args": {"value": 10}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 850, "ph": "B",
"name": "B", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22630, "ts": 854, "ph": "E",
"name": "B", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22631, "ts": 827, "ph": "B",
"name": "A", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22631, "ts": 835, "ph": "I",
"name": "Immediate Three", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22631, "ts": 845, "ph": "I",
"name": "I4", "args": {}},
{"cat": "PERF", "pid": 22630, "tid": 22631, "ts": 854, "ph": "E",
"name": "A", "args": {}},
{"cat": "__metadata", "pid": 22630, "tid": 22630, "ts": 0, "ph": "M",
"name": "thread_name", "args": {"name": "threadA"}},
{"cat": "__metadata", "pid": 22630, "tid": 22631, "ts": 0, "ph": "M",
"name": "thread_name", "args": {"name": "threadB"}},
{"cat": "__metadata", "pid": 22630, "tid": 22632, "ts": 0, "ph": "M",
"name": "thread_name", "args": {"name": "threadC"}}
]
\ No newline at end of file
[
{"cat": "X", "pid": 30, "tid": 30, "ts": 826, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 30, "ts": 827, "ph": "B", "name": "Asub",
"args": {}},
{"cat": "X", "pid": 30, "tid": 30, "ts": 828, "ph": "E", "name": "Asub",
"args": {}},
{"cat": "X", "pid": 30, "tid": 30, "ts": 829, "ph": "B", "name": "Asub",
"args": {}},
{"cat": "X", "pid": 30, "tid": 30, "ts": 832, "ph": "E", "name": "Asub",
"args": {}},
{"cat": "X", "pid": 30, "tid": 30, "ts": 833, "ph": "E", "name": "",
"args": {}},
{"cat": "X", "pid": 30, "tid": 31, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 31, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 32, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 32, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 33, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 33, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 34, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 34, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 35, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 35, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 36, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 36, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 37, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 37, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 38, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 38, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 39, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 39, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 10, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 10, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 31, "tid": 11, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 31, "tid": 11, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 12, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 12, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 13, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 13, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 14, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 14, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 15, "ts": 840, "ph": "B", "name": "A",
"args": {}},
{"cat": "X", "pid": 30, "tid": 15, "ts": 848, "ph": "E", "name": "A",
"args": {}},
{"cat": "__metadata", "pid": 30, "tid": 14, "ts": 0, "ph": "M",
"name": "thread_name", "args": {"name": "thread12345678B"}},
{"cat": "__metadata", "pid": 30, "tid": 15, "ts": 0, "ph": "M",
"name": "thread_name", "args": {"name": "threadA"}}
]
\ No newline at end of file
[
{"name": "a", "args": {},"pid": 52, "ts": 9524, "cat": "foo", "tid": 53,
"ph": "B"},
{"name": "a", "args": {},"pid": 52, "ts": 9560, "cat": "foo", "tid": 53,
"ph": "E"},
{"name": "b", "args": {},"pid": 52, "ts": 9629, "cat": "foo", "tid": 53,
"ph": "B"},
{"name": "b", "args": {},"pid": 52, "ts": 9631, "cat": "foo", "tid": 53,
"ph": "E"}
]
\ No newline at end of file
...@@ -21,18 +21,17 @@ found in the LICENSE file. ...@@ -21,18 +21,17 @@ found in the LICENSE file.
border-top: 1px solid #D0D0D0; border-top: 1px solid #D0D0D0;
} }
.timeline-slice-track { .timeline-canvas-based-track {
-webkit-box-orient: horizontal; -webkit-box-orient: horizontal;
-webkit-box-align: stretch; -webkit-box-align: stretch;
background-color: white; background-color: white;
display: -webkit-box; display: -webkit-box;
height: 18px;
margin: 0; margin: 0;
padding: 0; padding: 0;
padding-right: 5px; padding-right: 5px;
} }
.timeline-slice-track-title { .timeline-canvas-based-track-title {
overflow: hidden; overflow: hidden;
padding-right: 5px; padding-right: 5px;
text-align: right; text-align: right;
...@@ -40,13 +39,21 @@ found in the LICENSE file. ...@@ -40,13 +39,21 @@ found in the LICENSE file.
white-space: nowrap; white-space: nowrap;
} }
.timeline-slice-track-canvas-container { .timeline-canvas-based-track-canvas-container {
-webkit-box-flex: 1; -webkit-box-flex: 1;
width: 100%; width: 100%;
} }
.timeline-slice-track-canvas { .timeline-canvas-based-track-canvas {
-webkit-box-flex: 1; -webkit-box-flex: 1;
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.timeline-slice-track {
height: 18px;
}
.timeline-counter-track {
height: 30px;
}
...@@ -30,13 +30,15 @@ cr.define('tracing', function() { ...@@ -30,13 +30,15 @@ cr.define('tracing', function() {
* All time units are stored in milliseconds. * All time units are stored in milliseconds.
* @constructor * @constructor
*/ */
function TimelineSlice(title, colorId, start, args) { function TimelineSlice(title, colorId, start, args, opt_duration) {
this.title = title; this.title = title;
this.start = start; this.start = start;
this.colorId = colorId; this.colorId = colorId;
this.args = args; this.args = args;
this.didNotFinish = false; this.didNotFinish = false;
this.subSlices = []; this.subSlices = [];
if (opt_duration !== undefined)
this.duration = opt_duration;
} }
TimelineSlice.prototype = { TimelineSlice.prototype = {
...@@ -112,6 +114,23 @@ cr.define('tracing', function() { ...@@ -112,6 +114,23 @@ cr.define('tracing', function() {
this.minTimestamp = undefined; this.minTimestamp = undefined;
this.maxTimestamp = undefined; this.maxTimestamp = undefined;
} }
},
/**
* @return {String} A user-friendly name for this thread.
*/
get userFriendlyName() {
var tname = this.name || this.tid;
return this.parent.pid + ': ' + tname;
},
/**
* @return {String} User friendly details about this thread.
*/
get userFriendlyDetials() {
return 'pid: ' + this.parent.pid +
', tid: ' + this.tid +
(this.name ? ', name: ' + this.name : '');
} }
}; };
...@@ -122,7 +141,7 @@ cr.define('tracing', function() { ...@@ -122,7 +141,7 @@ cr.define('tracing', function() {
*/ */
TimelineThread.compare = function(x, y) { TimelineThread.compare = function(x, y) {
if (x.parent.pid != y.parent.pid) { if (x.parent.pid != y.parent.pid) {
return x.parent.pid - y.parent.pid; return TimelineProcess.compare(x.parent, y.parent.pid);
} }
if (x.name && y.name) { if (x.name && y.name) {
...@@ -139,6 +158,78 @@ cr.define('tracing', function() { ...@@ -139,6 +158,78 @@ cr.define('tracing', function() {
} }
}; };
/**
* Stores all the samples for a given counter.
* @constructor
*/
function TimelineCounter(parent, id, name) {
this.parent = parent;
this.id = id;
this.name = name;
this.seriesNames = [];
this.seriesColors = [];
this.timestamps = [];
this.samples = [];
}
TimelineCounter.prototype = {
__proto__: Object.prototype,
get numSeries() {
return this.seriesNames.length;
},
get numSamples() {
return this.timestamps.length;
},
/**
* Updates the bounds for this counter based on the samples it contains.
*/
updateBounds: function() {
if (this.seriesNames.length != this.seriesColors.length)
throw 'seriesNames.length must match seriesColors.length';
if (this.numSeries * this.numSamples != this.samples.length)
throw 'samples.length must be a multiple of numSamples.';
this.totals = [];
if (this.samples.length == 0) {
this.minTimestamp = undefined;
this.maxTimestamp = undefined;
this.maxTotal = 0;
return;
}
this.minTimestamp = this.timestamps[0];
this.maxTimestamp = this.timestamps[this.timestamps.length - 1];
var numSeries = this.numSeries;
var maxTotal = -Infinity;
for (var i = 0; i < this.timestamps.length; i++) {
var total = 0;
for (var j = 0; j < numSeries; j++) {
total += this.samples[i * numSeries + j];
this.totals.push(total);
}
if (total > maxTotal)
maxTotal = total;
}
this.maxTotal = maxTotal;
}
};
/**
* Comparison between counters that orders by pid, then name.
*/
TimelineCounter.compare = function(x, y) {
if (x.parent.pid != y.parent.pid) {
return TimelineProcess.compare(x.parent, y.parent.pid);
}
var tmp = x.name.localeCompare(y.name);
if (tmp == 0)
return x.tid - y.tid;
return tmp;
};
/** /**
* The TimelineProcess represents a single process in the * The TimelineProcess represents a single process in the
...@@ -149,6 +240,7 @@ cr.define('tracing', function() { ...@@ -149,6 +240,7 @@ cr.define('tracing', function() {
function TimelineProcess(pid) { function TimelineProcess(pid) {
this.pid = pid; this.pid = pid;
this.threads = {}; this.threads = {};
this.counters = {};
}; };
TimelineProcess.prototype = { TimelineProcess.prototype = {
...@@ -160,13 +252,35 @@ cr.define('tracing', function() { ...@@ -160,13 +252,35 @@ cr.define('tracing', function() {
return n; return n;
}, },
/**
* @return {TimlineThread} The thread identified by tid on this process,
* creating it if it doesn't exist.
*/
getOrCreateThread: function(tid) { getOrCreateThread: function(tid) {
if (!this.threads[tid]) if (!this.threads[tid])
this.threads[tid] = new TimelineThread(this, tid); this.threads[tid] = new TimelineThread(this, tid);
return this.threads[tid]; return this.threads[tid];
},
/**
* @return {TimlineCounter} The counter on this process named 'name',
* creating it if it doesn't exist.
*/
getOrCreateCounter: function(cat, name) {
var id = cat + '.' + name;
if (!this.counters[id])
this.counters[id] = new TimelineCounter(this, id, name);
return this.counters[id];
} }
}; };
/**
* Comparison between processes that orders by pid.
*/
TimelineProcess.compare = function(x, y) {
return x.pid - y.pid;
};
/** /**
* Computes a simplistic hashcode of the provide name. Used to chose colors * Computes a simplistic hashcode of the provide name. Used to chose colors
* for slices. * for slices.
...@@ -179,6 +293,20 @@ cr.define('tracing', function() { ...@@ -179,6 +293,20 @@ cr.define('tracing', function() {
return hash; return hash;
} }
/**
* The number of color IDs that getStringColorId can choose from.
*/
const numColorIds = 30;
/**
* @return {Number} A color ID that is stably associated to the provided via
* the getStringHash method.
*/
function getStringColorId(string) {
var hash = getStringHash(string);
return hash % numColorIds;
}
/** /**
* Builds a model from an array of TraceEvent objects. * Builds a model from an array of TraceEvent objects.
* @param {Array} events An array of TraceEvents created by * @param {Array} events An array of TraceEvents created by
...@@ -218,8 +346,7 @@ cr.define('tracing', function() { ...@@ -218,8 +346,7 @@ cr.define('tracing', function() {
// The ptid is a unique key for a thread in the trace. // The ptid is a unique key for a thread in the trace.
this.importErrors = []; this.importErrors = [];
// Threadstate // Threadstate.
const numColorIds = 30;
function ThreadState(tid) { function ThreadState(tid) {
this.openSlices = []; this.openSlices = [];
this.openNonNestedSlices = {}; this.openNonNestedSlices = {};
...@@ -229,8 +356,7 @@ cr.define('tracing', function() { ...@@ -229,8 +356,7 @@ cr.define('tracing', function() {
var nameToColorMap = {}; var nameToColorMap = {};
function getColor(name) { function getColor(name) {
if (!(name in nameToColorMap)) { if (!(name in nameToColorMap)) {
var hash = getStringHash(name); nameToColorMap[name] = getStringColorId(name);
nameToColorMap[name] = hash % numColorIds;
} }
return nameToColorMap[name]; return nameToColorMap[name];
} }
...@@ -328,6 +454,42 @@ cr.define('tracing', function() { ...@@ -328,6 +454,42 @@ cr.define('tracing', function() {
// TimelineSliceTrack's redraw() knows how to handle this. // TimelineSliceTrack's redraw() knows how to handle this.
processBegin(state, event); processBegin(state, event);
processEnd(state, event); processEnd(state, event);
} else if (event.ph == 'C') {
var ctr_name;
if (event.id !== undefined)
ctr_name = event.name + '[' + event.id + ']';
else
ctr_name = event.name;
var ctr = this.getOrCreateProcess(event.pid)
.getOrCreateCounter(event.cat, ctr_name);
// Initialize the counter's series fields if needed.
if (ctr.numSeries == 0) {
for (var seriesName in event.args) {
ctr.seriesNames.push(seriesName);
ctr.seriesColors.push(
getStringColorId(ctr.name + '.' + seriesName));
}
if (ctr.numSeries == 0) {
this.importErrors.push('Expected counter ' + event.name +
' to have at least one argument to use as a value.');
// Drop the counter.
delete ctr.parent.counters[ctr.name];
continue;
}
}
// Add the sample values.
ctr.timestamps.push(event.ts);
for (var i = 0; i < ctr.numSeries; i++) {
var seriesName = ctr.seriesNames[i];
if (event.args[seriesName] === undefined) {
ctr.samples.push(0);
continue;
}
ctr.samples.push(event.args[seriesName]);
}
} else if (event.ph == 'M') { } else if (event.ph == 'M') {
if (event.name == 'thread_name') { if (event.name == 'thread_name') {
var thread = this.getOrCreateProcess(event.pid) var thread = this.getOrCreateProcess(event.pid)
...@@ -405,6 +567,16 @@ cr.define('tracing', function() { ...@@ -405,6 +567,16 @@ cr.define('tracing', function() {
wmax = Math.max(wmax, thread.maxTimestamp); wmax = Math.max(wmax, thread.maxTimestamp);
} }
} }
var counters = this.getAllCounters();
for (var tI = 0; tI < counters.length; tI++) {
var counter = counters[tI];
counter.updateBounds();
if (counter.minTimestamp != undefined &&
counter.maxTimestamp != undefined) {
wmin = Math.min(wmin, counter.minTimestamp);
wmax = Math.max(wmax, counter.maxTimestamp);
}
}
this.minTimestamp = wmin; this.minTimestamp = wmin;
this.maxTimestamp = wmax; this.maxTimestamp = wmax;
}, },
...@@ -432,7 +604,12 @@ cr.define('tracing', function() { ...@@ -432,7 +604,12 @@ cr.define('tracing', function() {
shiftSubRow(thread.nonNestedSubRows[tSR]); shiftSubRow(thread.nonNestedSubRows[tSR]);
} }
} }
var counters = this.getAllCounters();
for (var tI = 0; tI < counters.length; tI++) {
var counter = counters[tI];
for (var sI = 0; sI < counter.timestamps.length; sI++)
counter.timestamps[sI] = (counter.timestamps[sI] - timeBase) / 1000;
}
this.updateBounds(); this.updateBounds();
}, },
...@@ -445,14 +622,30 @@ cr.define('tracing', function() { ...@@ -445,14 +622,30 @@ cr.define('tracing', function() {
} }
} }
return threads; return threads;
},
/**
* @return {Array} An array of all the counters in the model.
*/
getAllCounters: function() {
var counters = [];
for (var pid in this.processes) {
var process = this.processes[pid];
for (var tid in process.counters) {
counters.push(process.counters[tid]);
}
}
return counters;
} }
}; };
return { return {
getStringHash: getStringHash, getStringHash: getStringHash,
getStringColorId: getStringColorId,
TimelineSlice: TimelineSlice, TimelineSlice: TimelineSlice,
TimelineThread: TimelineThread, TimelineThread: TimelineThread,
TimelineCounter: TimelineCounter,
TimelineProcess: TimelineProcess, TimelineProcess: TimelineProcess,
TimelineModel: TimelineModel TimelineModel: TimelineModel
}; };
......
<!DOCTYPE HTML>
<html>
<!--
Copyright (c) 2011 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.
-->
<head i18n-values="dir:textdirection;">
<title>Interactive Timeline Tests</title>
<link rel="stylesheet" href="timeline.css">
<script src="../shared/js/cr.js"></script>
<script src="../shared/js/cr/event_target.js"></script>
<script src="../shared/js/cr/ui.js"></script>
<script src="../shared/js/util.js"></script>
<script src="timeline_model.js"></script>
<script src="sorted_array_utils.js"></script>
<script src="measuring_stick.js"></script>
<script src="timeline.js"></script>
<script src="timeline_track.js"></script>
<script src="fast_rect_renderer.js"></script>
<script src="test_utils.js"></script>
</head>
<body>
<div class="timeline-test" src="./tests/trivial_trace.json" create-detached=1>
</div>
<div class="timeline-test" src="./tests/trivial_trace.json">
</div>
<div class="timeline-test" src="./tests/simple_trace.json">
</div>
<div class="timeline-test" src="./tests/instance_counters.json">
</div>
<div class="timeline-test" src="./tests/nonnested_trace.json">
</div>
<div class="timeline-test" src="./tests/tall_trace.json">
</div>
<div class="timeline-test" src="./tests/big_trace.json">
</div>
<div class="timeline-test" src="./tests/huge_trace.json">
</div>
<script>
function load(parentEl) {
var src = parentEl.getAttribute('src');
if (document.location.hash && document.location.hash.substring(1) != src) {
parentEl.hidden = true;
return;
}
parentEl.hidden = false;
parentEl.textContent = '';
var titleEl = document.createElement('h3');
var linkEl = document.createElement('a');
linkEl.textContent = src;
linkEl.href = '#' + src;
titleEl.appendChild(linkEl);
var containerEl = document.createElement('div');
containerEl.tabIndex = 0;
containerEl.style.border = '1px solid red';
var timelineEl = document.createElement('div');
cr.ui.decorate(timelineEl, tracing.Timeline);
timelineEl.focusElement = containerEl;
parentEl.appendChild(titleEl);
parentEl.appendChild(containerEl);
// Creating attached vs detached stress tests the canvas- and viewport-
// setup code.
var create_detached = parentEl.getAttribute('create-attached') == 1;
if (create_detached) {
containerEl.appendChild(timelineEl);
test_utils.getJSON(src, function(events) {
var model = new tracing.TimelineModel(events);
timelineEl.model = model;
});
} else {
test_utils.getJSON(src, function(events) {
var model = new tracing.TimelineModel(events);
timelineEl.model = model;
containerEl.appendChild(timelineEl);
});
}
}
function onLoad() {
Array.prototype.forEach.call(document.querySelectorAll('.timeline-test'),
load);
}
document.addEventListener('DOMContentLoaded', onLoad);
window.addEventListener('hashchange', onLoad);
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<!--
Copyright (c) 2010 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.
-->
<head i18n-values="dir:textdirection;">
<title>TimelineTrack tests</title>
<script
src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js">
</script>
<script>
goog.require('goog.testing.jsunit');
</script>
<style>
* {
box-sizing: border-box;
-webkit-user-select: none;
}
.timeline-container {
border: 1px solid red;
}
</style>
<link rel="stylesheet" href="timeline.css">
<script src="../shared/js/cr.js"></script>
<script src="../shared/js/cr/event_target.js"></script>
<script src="../shared/js/cr/ui.js"></script>
<script src="../shared/js/util.js"></script>
<script src="timeline_model.js"></script>
<script src="sorted_array_utils.js"></script>
<script src="measuring_stick.js"></script>
<script src="timeline.js"></script>
<script src="timeline_track.js"></script>
<script src="fast_rect_renderer.js"></script>
</head>
<body>
<script>
</script>
<script>
var TimelineCounter = tracing.TimelineCounter;
var TimelineCounterTrack = tracing.TimelineCounterTrack;
var TimelineSliceTrack = tracing.TimelineSliceTrack;
var TimelineSlice = tracing.TimelineSlice;
var TimelineViewport = tracing.TimelineViewport;
var testDivs = {};
function getTestDiv(name) {
if (!testDivs[name]) {
testDivs[name] = document.createElement('div');
document.body.appendChild(testDivs[name]);
}
testDivs[name].textContent = '';
return testDivs[name];
}
function testBasicSlices() {
var testEl = getTestDiv('testBasicSlices');
var track = TimelineSliceTrack();
testEl.appendChild(track);
track.heading = 'testBasicSlices';
track.slices = [
new TimelineSlice('a', 0, 1, {}, 1),
new TimelineSlice('b', 1, 2.1, {}, 4.8),
new TimelineSlice('b', 1, 7, {}, 0.5),
new TimelineSlice('c', 2, 7.6, {}, 0.4)
];
track.viewport = new TimelineViewport(testEl);
track.viewport.setPanAndScale(0,
track.clientWidth / (1.1 * track.slices[track.slices.length - 1].end));
}
function testShrinkingSliceSizes() {
var testEl = getTestDiv('testShrinkingSliceSizes');
var track = TimelineSliceTrack();
testEl.appendChild(track);
track.heading = 'testShrinkingSliceSizes';
var x = 0;
var widths = [10, 5, 4, 3, 2, 1, 0.5, 0.4, 0.3, 0.2, 0.1, 0.05];
var slices = [];
for (var i = 0; i < widths.length; i++) {
var s = new TimelineSlice('a', 1, x, {}, widths[i]);
x += s.duration + 0.5;
slices.push(s);
}
track.slices = slices;
track.viewport = new TimelineViewport(testEl);
track.viewport.setPanAndScale(0,
track.clientWidth / (1.1 * track.slices[track.slices.length - 1].end));
}
function testPick() {
var testEl = getTestDiv('testPick');
var track = TimelineSliceTrack();
testEl.appendChild(track);
track.heading = 'testPick';
track.headingWidth = '100px';
track.slices = [
new TimelineSlice('a', 0, 1, {}, 1),
new TimelineSlice('b', 1, 2.1, {}, 4.8)
];
track.style.width = '500px';
track.viewport = new TimelineViewport(testEl);
track.viewport.setPanAndScale(0,
track.clientWidth / (1.1 * track.slices[track.slices.length - 1].end));
var clientRect = track.getBoundingClientRect();
var hits = [];
track.pick(1.5, clientRect.top + 5, function(x, y, z) { hits.push(z); });
assertEquals(track.slices[0], hits[0]);
hits = [];
track.pick(2, clientRect.top + 5, function(x, y, z) { hits.push(z); });
assertEquals(0, hits.length);
hits = [];
track.pick(6.8, clientRect.top + 5, function(x, y, z) { hits.push(z); });
assertEquals(track.slices[1], hits[0]);
hits = [];
track.pick(6.9, clientRect.top + 5, function(x, y, z) { hits.push(z); });
assertEquals(0, hits.length);
}
function testBasicCounter() {
var testEl = getTestDiv('testBasicCounter');
var ctr = new TimelineCounter(undefined, 'testBasicCounter', 'testBasicCounter');
ctr.numSeries = 1;
ctr.seriesNames = ['value1', 'value2'];
ctr.seriesColors = [tracing.getStringColorId('testBasicCounter.value1'),
tracing.getStringColorId('testBasicCounter.value2')];
ctr.timestamps = [0, 1, 2, 3, 4, 5, 6, 7];
ctr.samples = [0, 5,
3, 3,
1, 1,
2, 1.1,
3, 0,
1, 7,
3, 0,
3.1, 0.5];
ctr.updateBounds();
var track = TimelineCounterTrack();
testEl.appendChild(track);
track.heading = ctr.name;
track.counter = ctr;
track.viewport = new TimelineViewport(testEl);
track.viewport.setPanAndScale(0,
track.clientWidth / (1.1 * ctr.maxTimestamp));
}
</script>
</body>
</html>
...@@ -75,6 +75,7 @@ cr.define('tracing', function() { ...@@ -75,6 +75,7 @@ cr.define('tracing', function() {
this.timeline_.detach(); this.timeline_.detach();
this.timeline_ = new tracing.Timeline(); this.timeline_ = new tracing.Timeline();
this.timeline_.model = this.timelineModel_; this.timeline_.model = this.timelineModel_;
this.timeline_.focusElement = this.parentElement;
this.timelineContainer_.appendChild(this.timeline_); this.timelineContainer_.appendChild(this.timeline_);
this.timeline_.addEventListener('selectionChange', this.timeline_.addEventListener('selectionChange',
this.onSelectionChangedBoundToThis_); this.onSelectionChangedBoundToThis_);
......
...@@ -27,13 +27,6 @@ cr.define('tracing', function() { ...@@ -27,13 +27,6 @@ cr.define('tracing', function() {
this.traceEvents_ = []; this.traceEvents_ = [];
if (browserBridge.debugMode) {
var tracingControllerTests = document.createElement('script');
tracingControllerTests.src =
'./tracing/tracing_controller_tests.js';
document.body.appendChild(tracingControllerTests);
}
this.onKeydownBoundToThis_ = this.onKeydown_.bind(this); this.onKeydownBoundToThis_ = this.onKeydown_.bind(this);
this.onKeypressBoundToThis_ = this.onKeypress_.bind(this); this.onKeypressBoundToThis_ = this.onKeypress_.bind(this);
...@@ -81,12 +74,8 @@ cr.define('tracing', function() { ...@@ -81,12 +74,8 @@ cr.define('tracing', function() {
this.statusDiv_.textContent = 'Tracing active.'; this.statusDiv_.textContent = 'Tracing active.';
this.traceEvents_ = []; this.traceEvents_ = [];
if (!browserBridge.debugMode) { chrome.send('beginTracing');
chrome.send('beginTracing'); this.beginRequestBufferPercentFull_();
this.beginRequestBufferPercentFull_();
} else {
tracing.tracingControllerTestHarness.beginTracing();
}
this.tracingEnabled_ = true; this.tracingEnabled_ = true;
...@@ -166,11 +155,7 @@ cr.define('tracing', function() { ...@@ -166,11 +155,7 @@ cr.define('tracing', function() {
// delay sending endTracingAsync until we get a chance to // delay sending endTracingAsync until we get a chance to
// update the screen... // update the screen...
window.setTimeout(function() { window.setTimeout(function() {
if (!browserBridge.debugMode) { chrome.send('endTracingAsync');
chrome.send('endTracingAsync');
} else {
tracing.tracingControllerTestHarness.endTracing();
}
}, 100); }, 100);
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment