1<!DOCTYPE html> 2<!-- 3Copyright (c) 2013 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/model/timed_event.html"> 9<link rel="import" href="/tracing/value/unit.html"> 10 11<script> 12'use strict'; 13 14/** 15 * @fileoverview Provides the Slice class. 16 */ 17tr.exportTo('tr.model', function() { 18 /** 19 * A Slice represents an interval of time plus parameters associated 20 * with that interval. 21 * 22 * @constructor 23 */ 24 function Slice(category, title, colorId, start, args, opt_duration, 25 opt_cpuStart, opt_cpuDuration, opt_argsStripped, 26 opt_bind_id) { 27 tr.model.TimedEvent.call(this, start); 28 29 this.category = category || ''; 30 this.title = title; 31 this.colorId = colorId; 32 this.args = args; 33 this.startStackFrame = undefined; 34 this.endStackFrame = undefined; 35 this.didNotFinish = false; 36 this.inFlowEvents = []; 37 this.outFlowEvents = []; 38 this.subSlices = []; 39 this.selfTime = undefined; 40 this.cpuSelfTime = undefined; 41 this.important = false; 42 this.parentContainer = undefined; 43 this.argsStripped = false; 44 45 this.bind_id_ = opt_bind_id; 46 47 // parentSlice and isTopLevel will be set by SliceGroup. 48 this.parentSlice = undefined; 49 this.isTopLevel = false; 50 // After SliceGroup processes Slices, isTopLevel should be equivalent to 51 // !parentSlice. 52 53 if (opt_duration !== undefined) 54 this.duration = opt_duration; 55 56 if (opt_cpuStart !== undefined) 57 this.cpuStart = opt_cpuStart; 58 59 if (opt_cpuDuration !== undefined) 60 this.cpuDuration = opt_cpuDuration; 61 62 if (opt_argsStripped !== undefined) 63 this.argsStripped = true; 64 } 65 66 Slice.prototype = { 67 __proto__: tr.model.TimedEvent.prototype, 68 69 70 get analysisTypeName() { 71 return this.title; 72 }, 73 74 get userFriendlyName() { 75 return 'Slice ' + this.title + ' at ' + 76 tr.v.Unit.byName.timeStampInMs.format(this.start); 77 }, 78 79 get stableId() { 80 var parentSliceGroup = this.parentContainer.sliceGroup; 81 return parentSliceGroup.stableId + '.' + 82 parentSliceGroup.slices.indexOf(this); 83 }, 84 85 findDescendentSlice: function(targetTitle) { 86 if (!this.subSlices) 87 return undefined; 88 89 for (var i = 0; i < this.subSlices.length; i++) { 90 if (this.subSlices[i].title == targetTitle) 91 return this.subSlices[i]; 92 var slice = this.subSlices[i].findDescendentSlice(targetTitle); 93 if (slice) return slice; 94 } 95 return undefined; 96 }, 97 98 get mostTopLevelSlice() { 99 var curSlice = this; 100 while (curSlice.parentSlice) 101 curSlice = curSlice.parentSlice; 102 103 return curSlice; 104 }, 105 106 getProcess: function() { 107 var thread = this.parentContainer; 108 if (thread && thread.getProcess) 109 return thread.getProcess(); 110 return undefined; 111 }, 112 113 get model() { 114 var process = this.getProcess(); 115 if (process !== undefined) 116 return this.getProcess().model; 117 return undefined; 118 }, 119 120 /** 121 * Obtains all subsequent slices of this slice. 122 * 123 * Subsequent slices are slices that get executed after a particular 124 * slice, i.e., all the functions that are called after the current one. 125 * 126 * For instance, E.iterateAllSubsequentSlices() in the following example: 127 * [ A ] 128 * [ B][ D ][ G ] 129 * [C] [E][F] [H] 130 * will pass F, G, then H to the provided callback. 131 * 132 * The reason we need subsequent slices of a particular slice is that 133 * when there is flow event goes into, e.g., E, we only want to highlight 134 * E's subsequent slices to indicate the execution order. 135 * 136 * The idea to calculate the subsequent slices of slice E is to view 137 * the slice group as a tree where the top-level slice A is the root node. 138 * The preorder depth-first-search (DFS) order is naturally equivalent 139 * to the function call order. We just need to perform a DFS, and start 140 * recording the slices after we see the occurance of E. 141 */ 142 iterateAllSubsequentSlices: function(callback, opt_this) { 143 var parentStack = []; 144 var started = false; 145 146 // get the root node and push it to the DFS stack 147 var topmostSlice = this.mostTopLevelSlice; 148 parentStack.push(topmostSlice); 149 150 // Using the stack to perform DFS 151 while (parentStack.length !== 0) { 152 var curSlice = parentStack.pop(); 153 154 if (started) 155 callback.call(opt_this, curSlice); 156 else 157 started = (curSlice.guid === this.guid); 158 159 for (var i = curSlice.subSlices.length - 1; i >= 0; i--) { 160 parentStack.push(curSlice.subSlices[i]); 161 } 162 } 163 }, 164 165 get subsequentSlices() { 166 var res = []; 167 168 this.iterateAllSubsequentSlices(function(subseqSlice) { 169 res.push(subseqSlice); 170 }); 171 172 return res; 173 }, 174 175 /** 176 * Obtains the parents of a slice, from the most immediate to the root. 177 * 178 * For instance, E.iterateAllAncestors() in the following example: 179 * [ A ] 180 * [ B][ D ][ G ] 181 * [C] [E][F] [H] 182 * will pass D, then A to the provided callback, in the order from the 183 * leaves to the root. 184 */ 185 iterateAllAncestors: function(callback, opt_this) { 186 var curSlice = this; 187 188 while (curSlice.parentSlice) { 189 curSlice = curSlice.parentSlice; 190 callback.call(opt_this, curSlice); 191 } 192 }, 193 194 get ancestorSlices() { 195 var res = []; 196 197 this.iterateAllAncestors(function(ancestor) { 198 res.push(ancestor); 199 }); 200 201 return res; 202 }, 203 204 iterateEntireHierarchy: function(callback, opt_this) { 205 var mostTopLevelSlice = this.mostTopLevelSlice; 206 callback.call(opt_this, mostTopLevelSlice); 207 mostTopLevelSlice.iterateAllSubsequentSlices(callback, opt_this); 208 }, 209 210 get entireHierarchy() { 211 var res = []; 212 213 this.iterateEntireHierarchy(function(slice) { 214 res.push(slice); 215 }); 216 217 return res; 218 }, 219 220 /** 221 * Returns this slice, and its ancestor and subsequent slices. 222 * 223 * For instance, E.ancestorAndSubsequentSlices in the following example: 224 * [ A ] 225 * [ B][ D ][ G ] 226 * [C] [E][F] [H] 227 * will return E, D, A, F, G, and H, where E is itself, D and A are 228 * E's ancestors, and F, G, and H are subsequent slices of E 229 */ 230 get ancestorAndSubsequentSlices() { 231 var res = []; 232 233 res.push(this); 234 235 this.iterateAllAncestors(function(aSlice) { 236 res.push(aSlice); 237 }); 238 239 this.iterateAllSubsequentSlices(function(sSlice) { 240 res.push(sSlice); 241 }); 242 243 return res; 244 }, 245 246 iterateAllDescendents: function(callback, opt_this) { 247 this.subSlices.forEach(callback, opt_this); 248 this.subSlices.forEach(function(subSlice) { 249 subSlice.iterateAllDescendents(callback, opt_this); 250 }, opt_this); 251 }, 252 253 get descendentSlices() { 254 var res = []; 255 256 this.iterateAllDescendents(function(des) { 257 res.push(des); 258 }); 259 260 return res; 261 } 262 263 }; 264 265 return { 266 Slice: Slice 267 }; 268}); 269</script> 270 271