blob: cba6d0149775b68e52094469052e2127e8bba98f [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';
tv.exportTo('tv.c.tracks', function() {
/**
* Visualizes a Process's state using a series of rects to represent activity.
* @constructor
*/
var ProcessSummaryTrack = tv.b.ui.define('process-summary-track',
tv.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 = tv.b.ui.getColorIdForReservedName('generic_work');
var pushRect = function(start, end, slice) {
rects.push({
start: start,
end: end,
duration: end - start,
colorId: slice ? slice.colorId : genericColorId,
title: slice ? slice.title : undefined
});
}
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__: tv.c.tracks.RectTrack.prototype,
decorate: function(viewport) {
tv.c.tracks.RectTrack.prototype.decorate.call(this, viewport);
this.classList.add('inverse-expand');
},
get process() {
return this.process_;
},
set process(process) {
this.process_ = process;
this.rects = ProcessSummaryTrack.buildRectsFromProcess(process);
},
getModelEventFromItem: function(thing) {
// Do nothing, since not selectable
return undefined;
}
};
return {
ProcessSummaryTrack: ProcessSummaryTrack
};
});
</script>