Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sdk/CPUProfileDataModel.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4
5 /** 4 /**
6 * @constructor 5 * @unrestricted
7 * @extends {WebInspector.ProfileNode}
8 * @param {!ProfilerAgent.ProfileNode} node
9 * @param {number} sampleTime
10 */ 6 */
11 WebInspector.CPUProfileNode = function(node, sampleTime) 7 WebInspector.CPUProfileNode = class extends WebInspector.ProfileNode {
12 { 8 /**
9 * @param {!ProfilerAgent.ProfileNode} node
10 * @param {number} sampleTime
11 */
12 constructor(node, sampleTime) {
13 var callFrame = node.callFrame || /** @type {!RuntimeAgent.CallFrame} */ ({ 13 var callFrame = node.callFrame || /** @type {!RuntimeAgent.CallFrame} */ ({
14 // Backward compatibility for old SamplingHeapProfileNode format. 14 // Backward compatibility for old SamplingHeapProfileNode format.
15 functionName: node["functionName"], 15 functionName: node['functionName'],
16 scriptId: node["scriptId"], 16 scriptId: node['scriptId'],
17 url: node["url"], 17 url: node['url'],
18 lineNumber: node["lineNumber"] - 1, 18 lineNumber: node['lineNumber'] - 1,
19 columnNumber: node["columnNumber"] - 1 19 columnNumber: node['columnNumber'] - 1
20 }); 20 });
21 WebInspector.ProfileNode.call(this, callFrame); 21 super(callFrame);
22 this.id = node.id; 22 this.id = node.id;
23 this.self = node.hitCount * sampleTime; 23 this.self = node.hitCount * sampleTime;
24 this.positionTicks = node.positionTicks; 24 this.positionTicks = node.positionTicks;
25 // Compatibility: legacy backends could provide "no reason" for optimized fu nctions. 25 // Compatibility: legacy backends could provide "no reason" for optimized fu nctions.
26 this.deoptReason = node.deoptReason && node.deoptReason !== "no reason" ? no de.deoptReason : null; 26 this.deoptReason = node.deoptReason && node.deoptReason !== 'no reason' ? no de.deoptReason : null;
27 }; 27 }
28
29 WebInspector.CPUProfileNode.prototype = {
30 __proto__: WebInspector.ProfileNode.prototype
31 }; 28 };
32 29
33 /** 30 /**
34 * @constructor 31 * @unrestricted
35 * @extends {WebInspector.ProfileTreeModel}
36 * @param {!ProfilerAgent.Profile} profile
37 */ 32 */
38 WebInspector.CPUProfileDataModel = function(profile) 33 WebInspector.CPUProfileDataModel = class extends WebInspector.ProfileTreeModel {
39 { 34 /**
40 WebInspector.ProfileTreeModel.call(this); 35 * @param {!ProfilerAgent.Profile} profile
41 var isLegacyFormat = !!profile["head"]; 36 */
37 constructor(profile) {
38 super();
39 var isLegacyFormat = !!profile['head'];
42 if (isLegacyFormat) { 40 if (isLegacyFormat) {
43 // Legacy format contains raw timestamps and start/stop times are in sec onds. 41 // Legacy format contains raw timestamps and start/stop times are in secon ds.
44 this.profileStartTime = profile.startTime * 1000; 42 this.profileStartTime = profile.startTime * 1000;
45 this.profileEndTime = profile.endTime * 1000; 43 this.profileEndTime = profile.endTime * 1000;
46 this.timestamps = profile.timestamps; 44 this.timestamps = profile.timestamps;
47 this._compatibilityConversionHeadToNodes(profile); 45 this._compatibilityConversionHeadToNodes(profile);
48 } else { 46 } else {
49 // Current format encodes timestamps as deltas. Start/stop times are in microseconds. 47 // Current format encodes timestamps as deltas. Start/stop times are in mi croseconds.
50 this.profileStartTime = profile.startTime / 1000; 48 this.profileStartTime = profile.startTime / 1000;
51 this.profileEndTime = profile.endTime / 1000; 49 this.profileEndTime = profile.endTime / 1000;
52 this.timestamps = this._convertTimeDeltas(profile); 50 this.timestamps = this._convertTimeDeltas(profile);
53 } 51 }
54 this.samples = profile.samples; 52 this.samples = profile.samples;
55 this.totalHitCount = 0; 53 this.totalHitCount = 0;
56 this.profileHead = this._translateProfileTree(profile.nodes); 54 this.profileHead = this._translateProfileTree(profile.nodes);
57 this.initialize(this.profileHead); 55 this.initialize(this.profileHead);
58 this._extractMetaNodes(); 56 this._extractMetaNodes();
59 if (this.samples) { 57 if (this.samples) {
60 this._buildIdToNodeMap(); 58 this._buildIdToNodeMap();
61 this._sortSamples(); 59 this._sortSamples();
62 this._normalizeTimestamps(); 60 this._normalizeTimestamps();
63 } 61 }
64 }; 62 }
65 63
66 WebInspector.CPUProfileDataModel.prototype = { 64 /**
65 * @param {!ProfilerAgent.Profile} profile
66 */
67 _compatibilityConversionHeadToNodes(profile) {
68 if (!profile.head || profile.nodes)
69 return;
70 /** @type {!Array<!ProfilerAgent.ProfileNode>} */
71 var nodes = [];
72 convertNodesTree(profile.head);
73 profile.nodes = nodes;
74 delete profile.head;
67 /** 75 /**
68 * @param {!ProfilerAgent.Profile} profile 76 * @param {!ProfilerAgent.ProfileNode} node
77 * @return {number}
69 */ 78 */
70 _compatibilityConversionHeadToNodes: function(profile) 79 function convertNodesTree(node) {
71 { 80 nodes.push(node);
72 if (!profile.head || profile.nodes) 81 node.children = (/** @type {!Array<!ProfilerAgent.ProfileNode>} */ (node.c hildren)).map(convertNodesTree);
73 return; 82 return node.id;
74 /** @type {!Array<!ProfilerAgent.ProfileNode>} */ 83 }
75 var nodes = []; 84 }
76 convertNodesTree(profile.head); 85
77 profile.nodes = nodes; 86 /**
78 delete profile.head; 87 * @param {!ProfilerAgent.Profile} profile
79 /** 88 * @return {?Array<number>}
80 * @param {!ProfilerAgent.ProfileNode} node 89 */
81 * @return {number} 90 _convertTimeDeltas(profile) {
82 */ 91 if (!profile.timeDeltas)
83 function convertNodesTree(node) 92 return null;
84 { 93 var lastTimeUsec = profile.startTime;
85 nodes.push(node); 94 var timestamps = new Array(profile.timeDeltas.length);
86 node.children = (/** @type {!Array<!ProfilerAgent.ProfileNode>} */(n ode.children)).map(convertNodesTree); 95 for (var i = 0; i < timestamps.length; ++i) {
87 return node.id; 96 lastTimeUsec += profile.timeDeltas[i];
88 } 97 timestamps[i] = lastTimeUsec;
89 }, 98 }
90 99 return timestamps;
100 }
101
102 /**
103 * @param {!Array<!ProfilerAgent.ProfileNode>} nodes
104 * @return {!WebInspector.CPUProfileNode}
105 */
106 _translateProfileTree(nodes) {
91 /** 107 /**
92 * @param {!ProfilerAgent.Profile} profile 108 * @param {!ProfilerAgent.ProfileNode} node
93 * @return {?Array<number>} 109 * @return {boolean}
94 */ 110 */
95 _convertTimeDeltas: function(profile) 111 function isNativeNode(node) {
96 { 112 if (node.callFrame)
97 if (!profile.timeDeltas) 113 return !!node.callFrame.url && node.callFrame.url.startsWith('native ');
98 return null; 114 return !!node.url && node.url.startsWith('native ');
99 var lastTimeUsec = profile.startTime; 115 }
100 var timestamps = new Array(profile.timeDeltas.length);
101 for (var i = 0; i < timestamps.length; ++i) {
102 lastTimeUsec += profile.timeDeltas[i];
103 timestamps[i] = lastTimeUsec;
104 }
105 return timestamps;
106 },
107
108 /** 116 /**
109 * @param {!Array<!ProfilerAgent.ProfileNode>} nodes 117 * @param {!Array<!ProfilerAgent.ProfileNode>} nodes
110 * @return {!WebInspector.CPUProfileNode}
111 */ 118 */
112 _translateProfileTree: function(nodes) 119 function buildChildrenFromParents(nodes) {
113 { 120 if (nodes[0].children)
114 /** 121 return;
115 * @param {!ProfilerAgent.ProfileNode} node 122 nodes[0].children = [];
116 * @return {boolean} 123 for (var i = 1; i < nodes.length; ++i) {
117 */ 124 var node = nodes[i];
118 function isNativeNode(node) 125 var parentNode = nodeByIdMap.get(node.parent);
119 { 126 if (parentNode.children)
120 if (node.callFrame) 127 parentNode.children.push(node.id);
121 return !!node.callFrame.url && node.callFrame.url.startsWith("na tive "); 128 else
122 return !!node.url && node.url.startsWith("native "); 129 parentNode.children = [node.id];
130 }
131 }
132 /** @type {!Map<number, !ProfilerAgent.ProfileNode>} */
133 var nodeByIdMap = new Map();
134 for (var i = 0; i < nodes.length; ++i) {
135 var node = nodes[i];
136 nodeByIdMap.set(node.id, node);
137 }
138 buildChildrenFromParents(nodes);
139 this.totalHitCount = nodes.reduce((acc, node) => acc + node.hitCount, 0);
140 var sampleTime = (this.profileEndTime - this.profileStartTime) / this.totalH itCount;
141 var keepNatives = !!WebInspector.moduleSetting('showNativeFunctionsInJSProfi le').get();
142 var root = nodes[0];
143 /** @type {!Map<number, number>} */
144 var idMap = new Map([[root.id, root.id]]);
145 var resultRoot = new WebInspector.CPUProfileNode(root, sampleTime);
146 var parentNodeStack = root.children.map(() => resultRoot);
147 var sourceNodeStack = root.children.map(id => nodeByIdMap.get(id));
148 while (sourceNodeStack.length) {
149 var parentNode = parentNodeStack.pop();
150 var sourceNode = sourceNodeStack.pop();
151 if (!sourceNode.children)
152 sourceNode.children = [];
153 var targetNode = new WebInspector.CPUProfileNode(sourceNode, sampleTime);
154 if (keepNatives || !isNativeNode(sourceNode)) {
155 parentNode.children.push(targetNode);
156 parentNode = targetNode;
157 } else {
158 parentNode.self += targetNode.self;
159 }
160 idMap.set(sourceNode.id, parentNode.id);
161 parentNodeStack.push.apply(parentNodeStack, sourceNode.children.map(() => parentNode));
162 sourceNodeStack.push.apply(sourceNodeStack, sourceNode.children.map(id => nodeByIdMap.get(id)));
163 }
164 if (this.samples)
165 this.samples = this.samples.map(id => idMap.get(id));
166 return resultRoot;
167 }
168
169 _sortSamples() {
170 var timestamps = this.timestamps;
171 if (!timestamps)
172 return;
173 var samples = this.samples;
174 var indices = timestamps.map((x, index) => index);
175 indices.sort((a, b) => timestamps[a] - timestamps[b]);
176 for (var i = 0; i < timestamps.length; ++i) {
177 var index = indices[i];
178 if (index === i)
179 continue;
180 // Move items in a cycle.
181 var savedTimestamp = timestamps[i];
182 var savedSample = samples[i];
183 var currentIndex = i;
184 while (index !== i) {
185 samples[currentIndex] = samples[index];
186 timestamps[currentIndex] = timestamps[index];
187 currentIndex = index;
188 index = indices[index];
189 indices[currentIndex] = currentIndex;
190 }
191 samples[currentIndex] = savedSample;
192 timestamps[currentIndex] = savedTimestamp;
193 }
194 }
195
196 _normalizeTimestamps() {
197 var timestamps = this.timestamps;
198 if (!timestamps) {
199 // Support loading old CPU profiles that are missing timestamps.
200 // Derive timestamps from profile start and stop times.
201 var profileStartTime = this.profileStartTime;
202 var interval = (this.profileEndTime - profileStartTime) / this.samples.len gth;
203 timestamps = new Float64Array(this.samples.length + 1);
204 for (var i = 0; i < timestamps.length; ++i)
205 timestamps[i] = profileStartTime + i * interval;
206 this.timestamps = timestamps;
207 return;
208 }
209
210 // Convert samples from usec to msec
211 for (var i = 0; i < timestamps.length; ++i)
212 timestamps[i] /= 1000;
213 var averageSample = (timestamps.peekLast() - timestamps[0]) / (timestamps.le ngth - 1);
214 // Add an extra timestamp used to calculate the last sample duration.
215 this.timestamps.push(timestamps.peekLast() + averageSample);
216 this.profileStartTime = timestamps[0];
217 this.profileEndTime = timestamps.peekLast();
218 }
219
220 _buildIdToNodeMap() {
221 /** @type {!Map<number, !WebInspector.CPUProfileNode>} */
222 this._idToNode = new Map();
223 var idToNode = this._idToNode;
224 var stack = [this.profileHead];
225 while (stack.length) {
226 var node = stack.pop();
227 idToNode.set(node.id, node);
228 stack.push.apply(stack, node.children);
229 }
230 }
231
232 _extractMetaNodes() {
233 var topLevelNodes = this.profileHead.children;
234 for (var i = 0; i < topLevelNodes.length && !(this.gcNode && this.programNod e && this.idleNode); i++) {
235 var node = topLevelNodes[i];
236 if (node.functionName === '(garbage collector)')
237 this.gcNode = node;
238 else if (node.functionName === '(program)')
239 this.programNode = node;
240 else if (node.functionName === '(idle)')
241 this.idleNode = node;
242 }
243 }
244
245 /**
246 * @param {function(number, !WebInspector.CPUProfileNode, number)} openFrameCa llback
247 * @param {function(number, !WebInspector.CPUProfileNode, number, number, numb er)} closeFrameCallback
248 * @param {number=} startTime
249 * @param {number=} stopTime
250 */
251 forEachFrame(openFrameCallback, closeFrameCallback, startTime, stopTime) {
252 if (!this.profileHead || !this.samples)
253 return;
254
255 startTime = startTime || 0;
256 stopTime = stopTime || Infinity;
257 var samples = this.samples;
258 var timestamps = this.timestamps;
259 var idToNode = this._idToNode;
260 var gcNode = this.gcNode;
261 var samplesCount = samples.length;
262 var startIndex = timestamps.lowerBound(startTime);
263 var stackTop = 0;
264 var stackNodes = [];
265 var prevId = this.profileHead.id;
266 var sampleTime = timestamps[samplesCount];
267 var gcParentNode = null;
268
269 if (!this._stackStartTimes)
270 this._stackStartTimes = new Float64Array(this.maxDepth + 2);
271 var stackStartTimes = this._stackStartTimes;
272 if (!this._stackChildrenDuration)
273 this._stackChildrenDuration = new Float64Array(this.maxDepth + 2);
274 var stackChildrenDuration = this._stackChildrenDuration;
275
276 for (var sampleIndex = startIndex; sampleIndex < samplesCount; sampleIndex++ ) {
277 sampleTime = timestamps[sampleIndex];
278 if (sampleTime >= stopTime)
279 break;
280 var id = samples[sampleIndex];
281 if (id === prevId)
282 continue;
283 var node = idToNode.get(id);
284 var prevNode = idToNode.get(prevId);
285
286 if (node === gcNode) {
287 // GC samples have no stack, so we just put GC node on top of the last r ecorded sample.
288 gcParentNode = prevNode;
289 openFrameCallback(gcParentNode.depth + 1, gcNode, sampleTime);
290 stackStartTimes[++stackTop] = sampleTime;
291 stackChildrenDuration[stackTop] = 0;
292 prevId = id;
293 continue;
294 }
295 if (prevNode === gcNode) {
296 // end of GC frame
297 var start = stackStartTimes[stackTop];
298 var duration = sampleTime - start;
299 stackChildrenDuration[stackTop - 1] += duration;
300 closeFrameCallback(gcParentNode.depth + 1, gcNode, start, duration, dura tion - stackChildrenDuration[stackTop]);
301 --stackTop;
302 prevNode = gcParentNode;
303 prevId = prevNode.id;
304 gcParentNode = null;
305 }
306
307 while (node.depth > prevNode.depth) {
308 stackNodes.push(node);
309 node = node.parent;
310 }
311
312 // Go down to the LCA and close current intervals.
313 while (prevNode !== node) {
314 var start = stackStartTimes[stackTop];
315 var duration = sampleTime - start;
316 stackChildrenDuration[stackTop - 1] += duration;
317 closeFrameCallback(
318 prevNode.depth, /** @type {!WebInspector.CPUProfileNode} */ (prevNod e), start, duration,
319 duration - stackChildrenDuration[stackTop]);
320 --stackTop;
321 if (node.depth === prevNode.depth) {
322 stackNodes.push(node);
323 node = node.parent;
123 } 324 }
124 /** 325 prevNode = prevNode.parent;
125 * @param {!Array<!ProfilerAgent.ProfileNode>} nodes 326 }
126 */ 327
127 function buildChildrenFromParents(nodes) 328 // Go up the nodes stack and open new intervals.
128 { 329 while (stackNodes.length) {
129 if (nodes[0].children) 330 node = stackNodes.pop();
130 return; 331 openFrameCallback(node.depth, node, sampleTime);
131 nodes[0].children = []; 332 stackStartTimes[++stackTop] = sampleTime;
132 for (var i = 1; i < nodes.length; ++i) { 333 stackChildrenDuration[stackTop] = 0;
133 var node = nodes[i]; 334 }
134 var parentNode = nodeByIdMap.get(node.parent); 335
135 if (parentNode.children) 336 prevId = id;
136 parentNode.children.push(node.id); 337 }
137 else 338
138 parentNode.children = [node.id]; 339 if (idToNode.get(prevId) === gcNode) {
139 } 340 var start = stackStartTimes[stackTop];
140 } 341 var duration = sampleTime - start;
141 /** @type {!Map<number, !ProfilerAgent.ProfileNode>} */ 342 stackChildrenDuration[stackTop - 1] += duration;
142 var nodeByIdMap = new Map(); 343 closeFrameCallback(gcParentNode.depth + 1, node, start, duration, duration - stackChildrenDuration[stackTop]);
143 for (var i = 0; i < nodes.length; ++i) { 344 --stackTop;
144 var node = nodes[i]; 345 }
145 nodeByIdMap.set(node.id, node); 346
146 } 347 for (var node = idToNode.get(prevId); node.parent; node = node.parent) {
147 buildChildrenFromParents(nodes); 348 var start = stackStartTimes[stackTop];
148 this.totalHitCount = nodes.reduce((acc, node) => acc + node.hitCount, 0) ; 349 var duration = sampleTime - start;
149 var sampleTime = (this.profileEndTime - this.profileStartTime) / this.to talHitCount; 350 stackChildrenDuration[stackTop - 1] += duration;
150 var keepNatives = !!WebInspector.moduleSetting("showNativeFunctionsInJSP rofile").get(); 351 closeFrameCallback(
151 var root = nodes[0]; 352 node.depth, /** @type {!WebInspector.CPUProfileNode} */ (node), start, duration,
152 /** @type {!Map<number, number>} */ 353 duration - stackChildrenDuration[stackTop]);
153 var idMap = new Map([[root.id, root.id]]); 354 --stackTop;
154 var resultRoot = new WebInspector.CPUProfileNode(root, sampleTime); 355 }
155 var parentNodeStack = root.children.map(() => resultRoot); 356 }
156 var sourceNodeStack = root.children.map(id => nodeByIdMap.get(id)); 357
157 while (sourceNodeStack.length) { 358 /**
158 var parentNode = parentNodeStack.pop(); 359 * @param {number} index
159 var sourceNode = sourceNodeStack.pop(); 360 * @return {?WebInspector.CPUProfileNode}
160 if (!sourceNode.children) 361 */
161 sourceNode.children = []; 362 nodeByIndex(index) {
162 var targetNode = new WebInspector.CPUProfileNode(sourceNode, sampleT ime); 363 return this._idToNode.get(this.samples[index]) || null;
163 if (keepNatives || !isNativeNode(sourceNode)) { 364 }
164 parentNode.children.push(targetNode);
165 parentNode = targetNode;
166 } else {
167 parentNode.self += targetNode.self;
168 }
169 idMap.set(sourceNode.id, parentNode.id);
170 parentNodeStack.push.apply(parentNodeStack, sourceNode.children.map( () => parentNode));
171 sourceNodeStack.push.apply(sourceNodeStack, sourceNode.children.map( id => nodeByIdMap.get(id)));
172 }
173 if (this.samples)
174 this.samples = this.samples.map(id => idMap.get(id));
175 return resultRoot;
176 },
177
178 _sortSamples: function()
179 {
180 var timestamps = this.timestamps;
181 if (!timestamps)
182 return;
183 var samples = this.samples;
184 var indices = timestamps.map((x, index) => index);
185 indices.sort((a, b) => timestamps[a] - timestamps[b]);
186 for (var i = 0; i < timestamps.length; ++i) {
187 var index = indices[i];
188 if (index === i)
189 continue;
190 // Move items in a cycle.
191 var savedTimestamp = timestamps[i];
192 var savedSample = samples[i];
193 var currentIndex = i;
194 while (index !== i) {
195 samples[currentIndex] = samples[index];
196 timestamps[currentIndex] = timestamps[index];
197 currentIndex = index;
198 index = indices[index];
199 indices[currentIndex] = currentIndex;
200 }
201 samples[currentIndex] = savedSample;
202 timestamps[currentIndex] = savedTimestamp;
203 }
204 },
205
206 _normalizeTimestamps: function()
207 {
208 var timestamps = this.timestamps;
209 if (!timestamps) {
210 // Support loading old CPU profiles that are missing timestamps.
211 // Derive timestamps from profile start and stop times.
212 var profileStartTime = this.profileStartTime;
213 var interval = (this.profileEndTime - profileStartTime) / this.sampl es.length;
214 timestamps = new Float64Array(this.samples.length + 1);
215 for (var i = 0; i < timestamps.length; ++i)
216 timestamps[i] = profileStartTime + i * interval;
217 this.timestamps = timestamps;
218 return;
219 }
220
221 // Convert samples from usec to msec
222 for (var i = 0; i < timestamps.length; ++i)
223 timestamps[i] /= 1000;
224 var averageSample = (timestamps.peekLast() - timestamps[0]) / (timestamp s.length - 1);
225 // Add an extra timestamp used to calculate the last sample duration.
226 this.timestamps.push(timestamps.peekLast() + averageSample);
227 this.profileStartTime = timestamps[0];
228 this.profileEndTime = timestamps.peekLast();
229 },
230
231 _buildIdToNodeMap: function()
232 {
233 /** @type {!Map<number, !WebInspector.CPUProfileNode>} */
234 this._idToNode = new Map();
235 var idToNode = this._idToNode;
236 var stack = [this.profileHead];
237 while (stack.length) {
238 var node = stack.pop();
239 idToNode.set(node.id, node);
240 stack.push.apply(stack, node.children);
241 }
242 },
243
244 _extractMetaNodes: function()
245 {
246 var topLevelNodes = this.profileHead.children;
247 for (var i = 0; i < topLevelNodes.length && !(this.gcNode && this.progra mNode && this.idleNode); i++) {
248 var node = topLevelNodes[i];
249 if (node.functionName === "(garbage collector)")
250 this.gcNode = node;
251 else if (node.functionName === "(program)")
252 this.programNode = node;
253 else if (node.functionName === "(idle)")
254 this.idleNode = node;
255 }
256 },
257
258 /**
259 * @param {function(number, !WebInspector.CPUProfileNode, number)} openFrame Callback
260 * @param {function(number, !WebInspector.CPUProfileNode, number, number, nu mber)} closeFrameCallback
261 * @param {number=} startTime
262 * @param {number=} stopTime
263 */
264 forEachFrame: function(openFrameCallback, closeFrameCallback, startTime, sto pTime)
265 {
266 if (!this.profileHead || !this.samples)
267 return;
268
269 startTime = startTime || 0;
270 stopTime = stopTime || Infinity;
271 var samples = this.samples;
272 var timestamps = this.timestamps;
273 var idToNode = this._idToNode;
274 var gcNode = this.gcNode;
275 var samplesCount = samples.length;
276 var startIndex = timestamps.lowerBound(startTime);
277 var stackTop = 0;
278 var stackNodes = [];
279 var prevId = this.profileHead.id;
280 var sampleTime = timestamps[samplesCount];
281 var gcParentNode = null;
282
283 if (!this._stackStartTimes)
284 this._stackStartTimes = new Float64Array(this.maxDepth + 2);
285 var stackStartTimes = this._stackStartTimes;
286 if (!this._stackChildrenDuration)
287 this._stackChildrenDuration = new Float64Array(this.maxDepth + 2);
288 var stackChildrenDuration = this._stackChildrenDuration;
289
290 for (var sampleIndex = startIndex; sampleIndex < samplesCount; sampleInd ex++) {
291 sampleTime = timestamps[sampleIndex];
292 if (sampleTime >= stopTime)
293 break;
294 var id = samples[sampleIndex];
295 if (id === prevId)
296 continue;
297 var node = idToNode.get(id);
298 var prevNode = idToNode.get(prevId);
299
300 if (node === gcNode) {
301 // GC samples have no stack, so we just put GC node on top of th e last recorded sample.
302 gcParentNode = prevNode;
303 openFrameCallback(gcParentNode.depth + 1, gcNode, sampleTime);
304 stackStartTimes[++stackTop] = sampleTime;
305 stackChildrenDuration[stackTop] = 0;
306 prevId = id;
307 continue;
308 }
309 if (prevNode === gcNode) {
310 // end of GC frame
311 var start = stackStartTimes[stackTop];
312 var duration = sampleTime - start;
313 stackChildrenDuration[stackTop - 1] += duration;
314 closeFrameCallback(gcParentNode.depth + 1, gcNode, start, durati on, duration - stackChildrenDuration[stackTop]);
315 --stackTop;
316 prevNode = gcParentNode;
317 prevId = prevNode.id;
318 gcParentNode = null;
319 }
320
321 while (node.depth > prevNode.depth) {
322 stackNodes.push(node);
323 node = node.parent;
324 }
325
326 // Go down to the LCA and close current intervals.
327 while (prevNode !== node) {
328 var start = stackStartTimes[stackTop];
329 var duration = sampleTime - start;
330 stackChildrenDuration[stackTop - 1] += duration;
331 closeFrameCallback(prevNode.depth, /** @type {!WebInspector.CPUP rofileNode} */(prevNode), start, duration, duration - stackChildrenDuration[stac kTop]);
332 --stackTop;
333 if (node.depth === prevNode.depth) {
334 stackNodes.push(node);
335 node = node.parent;
336 }
337 prevNode = prevNode.parent;
338 }
339
340 // Go up the nodes stack and open new intervals.
341 while (stackNodes.length) {
342 node = stackNodes.pop();
343 openFrameCallback(node.depth, node, sampleTime);
344 stackStartTimes[++stackTop] = sampleTime;
345 stackChildrenDuration[stackTop] = 0;
346 }
347
348 prevId = id;
349 }
350
351 if (idToNode.get(prevId) === gcNode) {
352 var start = stackStartTimes[stackTop];
353 var duration = sampleTime - start;
354 stackChildrenDuration[stackTop - 1] += duration;
355 closeFrameCallback(gcParentNode.depth + 1, node, start, duration, du ration - stackChildrenDuration[stackTop]);
356 --stackTop;
357 }
358
359 for (var node = idToNode.get(prevId); node.parent; node = node.parent) {
360 var start = stackStartTimes[stackTop];
361 var duration = sampleTime - start;
362 stackChildrenDuration[stackTop - 1] += duration;
363 closeFrameCallback(node.depth, /** @type {!WebInspector.CPUProfileNo de} */(node), start, duration, duration - stackChildrenDuration[stackTop]);
364 --stackTop;
365 }
366 },
367
368 /**
369 * @param {number} index
370 * @return {?WebInspector.CPUProfileNode}
371 */
372 nodeByIndex: function(index)
373 {
374 return this._idToNode.get(this.samples[index]) || null;
375 },
376
377 __proto__: WebInspector.ProfileTreeModel.prototype
378 }; 365 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698