blob: 8192291c76d7ed86b55174a01e82f4365e85a3c8 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 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.
-->
<link rel="import" href="/core/tracks/rect_track.html">
<link rel="import" href="/base/ui.html">
<link rel="import" href="/base/ui/color_scheme.html">
<script>
'use strict';
tr.exportTo('tr.c.tracks', function() {
/**
* Visualizes a Process's state using a series of rects to represent activity.
* @constructor
*/
var ProcessSummaryTrack = tr.b.ui.define('process-summary-track',
tr.c.tracks.RectTrack);
ProcessSummaryTrack.buildRectsFromProcess = function(process) {
if (!process)
return [];
var ops = [];
// build list of start/end ops for each top level or important slice
var pushOp = function(isStart, time, slice) {
ops.push({
isStart: isStart,
time: time,
slice: slice
});
};
for (var tid in process.threads) {
var sliceGroup = process.threads[tid].sliceGroup;
sliceGroup.topLevelSlices.forEach(function(slice) {
pushOp(true, slice.start, undefined);
pushOp(false, slice.end, undefined);
});
sliceGroup.slices.forEach(function(slice) {
if (slice.important) {
pushOp(true, slice.start, slice);
pushOp(false, slice.end, slice);
}
});
}
ops.sort(function(a, b) { return a.time - b.time; });
var rects = [];
/**
* Build a row of rects which display one way for unimportant activity,
* and during important slices, show up as those important slices.
*
* If an important slice starts in the middle of another,
* just drop it on the floor.
*/
var genericColorId = tr.b.ui.getColorIdForReservedName('generic_work');
var pushRect = function(start, end, slice) {
rects.push(new tr.c.tracks.Rect(
slice, /* modelItem: show selection state of slice if present */
slice ? slice.title : '', /* title */
slice ? slice.colorId : genericColorId, /* colorId */
start, /* start */
end - start /* duration */));
}
var depth = 0;
var currentSlice = undefined;
var lastStart = undefined;
ops.forEach(function(op) {
depth += op.isStart ? 1 : -1;
if (currentSlice) {
// simply find end of current important slice
if (!op.isStart && op.slice == currentSlice) {
// important slice has ended
pushRect(lastStart, op.time, currentSlice);
lastStart = depth >= 1 ? op.time : undefined;
currentSlice = undefined;
}
} else {
if (op.isStart) {
if (depth == 1) {
lastStart = op.time;
currentSlice = op.slice;
} else if (op.slice) {
// switch to slice
if (op.time != lastStart) {
pushRect(lastStart, op.time, undefined);
lastStart = op.time;
}
currentSlice = op.slice;
}
} else {
if (depth == 0) {
pushRect(lastStart, op.time, undefined);
lastStart = undefined;
}
}
}
});
return rects;
};
ProcessSummaryTrack.prototype = {
__proto__: tr.c.tracks.RectTrack.prototype,
decorate: function(viewport) {
tr.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
},
get process() {
return this.process_;
},
set process(process) {
this.process_ = process;
this.rects = ProcessSummaryTrack.buildRectsFromProcess(process);
}
};
return {
ProcessSummaryTrack: ProcessSummaryTrack
};
});
</script>