// Copyright (c) 2012 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. 'use strict'; /** * @fileoverview Provides the TimelineAsyncSliceGroup class. */ base.require('timeline_slice'); base.exportTo('tracing', function() { var TimelineSlice = tracing.TimelineSlice; /** * A TimelineAsyncSlice represents an interval of time during which an * asynchronous operation is in progress. An AsyncSlice consumes no CPU time * itself and so is only associated with Threads at its start and end point. * * @constructor */ function TimelineAsyncSlice(category, title, colorId, start, args) { TimelineSlice.call(this, category, title, colorId, start, args); }; TimelineAsyncSlice.prototype = { __proto__: TimelineSlice.prototype, toJSON: function() { var obj = new Object(); var keys = Object.keys(this); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (typeof this[key] == 'function') continue; if (key == 'startThread' || key == 'endThread') { obj[key] = this[key].ptid; continue; } obj[key] = this[key]; } return obj; }, id: undefined, startThread: undefined, endThread: undefined, subSlices: undefined }; /** * A group of AsyncSlices. * @constructor */ function TimelineAsyncSliceGroup(name) { this.name = name; this.slices = []; } TimelineAsyncSliceGroup.prototype = { __proto__: Object.prototype, /** * Helper function that pushes the provided slice onto the slices array. */ push: function(slice) { this.slices.push(slice); }, /** * @return {Number} The number of slices in this group. */ get length() { return this.slices.length; }, /** * Shifts all the timestamps inside this group forward by the amount * specified. */ shiftTimestampsForward: function(amount) { for (var sI = 0; sI < this.slices.length; sI++) { var slice = this.slices[sI]; slice.start = (slice.start + amount); for (var sJ = 0; sJ < slice.subSlices.length; sJ++) slice.subSlices[sJ].start += amount; } }, /** * Updates the bounds for this group based on the slices it contains. */ updateBounds: function() { if (this.slices.length) { var minTimestamp = Number.MAX_VALUE; var maxTimestamp = -Number.MAX_VALUE; for (var i = 0; i < this.slices.length; i++) { if (this.slices[i].start < minTimestamp) minTimestamp = this.slices[i].start; if (this.slices[i].end > maxTimestamp) maxTimestamp = this.slices[i].end; } this.minTimestamp = minTimestamp; this.maxTimestamp = maxTimestamp; } else { this.minTimestamp = undefined; this.maxTimestamp = undefined; } }, /** * Breaks up this group into slices based on start thread. * * @return {Array} An array of TimelineAsyncSliceGroups where each group has * slices that started on the same thread. */ computeSubGroups: function() { var subGroupsByPTID = {}; for (var i = 0; i < this.slices.length; ++i) { var slice = this.slices[i]; var slicePTID = slice.startThread.ptid; if (!subGroupsByPTID[slicePTID]) subGroupsByPTID[slicePTID] = new TimelineAsyncSliceGroup(this.name); subGroupsByPTID[slicePTID].slices.push(slice); } var groups = []; for (var ptid in subGroupsByPTID) { var group = subGroupsByPTID[ptid]; group.updateBounds(); groups.push(group); } return groups; } }; return { TimelineAsyncSlice: TimelineAsyncSlice, TimelineAsyncSliceGroup: TimelineAsyncSliceGroup }; });