1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 'use strict'; 6 7 /** 8 * @fileoverview Provides the TimelineAsyncSliceGroup class. 9 */ 10 base.require('timeline_slice'); 11 base.exportTo('tracing', function() { 12 13 var TimelineSlice = tracing.TimelineSlice; 14 15 /** 16 * A TimelineAsyncSlice represents an interval of time during which an 17 * asynchronous operation is in progress. An AsyncSlice consumes no CPU time 18 * itself and so is only associated with Threads at its start and end point. 19 * 20 * @constructor 21 */ 22 function TimelineAsyncSlice(category, title, colorId, start, args) { 23 TimelineSlice.call(this, category, title, colorId, start, args); 24 }; 25 26 TimelineAsyncSlice.prototype = { 27 __proto__: TimelineSlice.prototype, 28 29 toJSON: function() { 30 var obj = new Object(); 31 var keys = Object.keys(this); 32 for (var i = 0; i < keys.length; i++) { 33 var key = keys[i]; 34 if (typeof this[key] == 'function') 35 continue; 36 if (key == 'startThread' || key == 'endThread') { 37 obj[key] = this[key].ptid; 38 continue; 39 } 40 obj[key] = this[key]; 41 } 42 return obj; 43 }, 44 45 id: undefined, 46 47 startThread: undefined, 48 49 endThread: undefined, 50 51 subSlices: undefined 52 }; 53 54 /** 55 * A group of AsyncSlices. 56 * @constructor 57 */ 58 function TimelineAsyncSliceGroup(name) { 59 this.name = name; 60 this.slices = []; 61 } 62 63 TimelineAsyncSliceGroup.prototype = { 64 __proto__: Object.prototype, 65 66 /** 67 * Helper function that pushes the provided slice onto the slices array. 68 */ 69 push: function(slice) { 70 this.slices.push(slice); 71 }, 72 73 /** 74 * @return {Number} The number of slices in this group. 75 */ 76 get length() { 77 return this.slices.length; 78 }, 79 80 /** 81 * Shifts all the timestamps inside this group forward by the amount 82 * specified. 83 */ 84 shiftTimestampsForward: function(amount) { 85 for (var sI = 0; sI < this.slices.length; sI++) { 86 var slice = this.slices[sI]; 87 slice.start = (slice.start + amount); 88 for (var sJ = 0; sJ < slice.subSlices.length; sJ++) 89 slice.subSlices[sJ].start += amount; 90 } 91 }, 92 93 /** 94 * Updates the bounds for this group based on the slices it contains. 95 */ 96 updateBounds: function() { 97 if (this.slices.length) { 98 var minTimestamp = Number.MAX_VALUE; 99 var maxTimestamp = -Number.MAX_VALUE; 100 for (var i = 0; i < this.slices.length; i++) { 101 if (this.slices[i].start < minTimestamp) 102 minTimestamp = this.slices[i].start; 103 if (this.slices[i].end > maxTimestamp) 104 maxTimestamp = this.slices[i].end; 105 } 106 this.minTimestamp = minTimestamp; 107 this.maxTimestamp = maxTimestamp; 108 } else { 109 this.minTimestamp = undefined; 110 this.maxTimestamp = undefined; 111 } 112 }, 113 114 /** 115 * Breaks up this group into slices based on start thread. 116 * 117 * @return {Array} An array of TimelineAsyncSliceGroups where each group has 118 * slices that started on the same thread. 119 */ 120 computeSubGroups: function() { 121 var subGroupsByPTID = {}; 122 for (var i = 0; i < this.slices.length; ++i) { 123 var slice = this.slices[i]; 124 var slicePTID = slice.startThread.ptid; 125 if (!subGroupsByPTID[slicePTID]) 126 subGroupsByPTID[slicePTID] = new TimelineAsyncSliceGroup(this.name); 127 subGroupsByPTID[slicePTID].slices.push(slice); 128 } 129 var groups = []; 130 for (var ptid in subGroupsByPTID) { 131 var group = subGroupsByPTID[ptid]; 132 group.updateBounds(); 133 groups.push(group); 134 } 135 return groups; 136 } 137 }; 138 139 return { 140 TimelineAsyncSlice: TimelineAsyncSlice, 141 TimelineAsyncSliceGroup: TimelineAsyncSliceGroup 142 }; 143 }); 144