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

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

Issue 1889963003: Revert of DevTools: extract CPU profile independent part of CPUProfileNode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months 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 4
5 /**
6 * @constructor
7 * @extends {WebInspector.ProfileNode}
8 * @param {!ProfilerAgent.CPUProfileNode} sourceNode
9 * @param {number} sampleTime
10 */
11 WebInspector.CPUProfileNode = function(sourceNode, sampleTime)
12 {
13 WebInspector.ProfileNode.call(this, sourceNode.functionName, sourceNode.scri ptId, sourceNode.url, sourceNode.lineNumber, sourceNode.columnNumber);
14 this.id = sourceNode.id;
15 this.self = sourceNode.hitCount * sampleTime;
16 this.callUID = sourceNode.callUID;
17 this.positionTicks = sourceNode.positionTicks;
18 this.deoptReason = sourceNode.deoptReason;
19 // TODO: Remove the following field in favor of this.self
20 this.selfTime = this.self;
21 }
22
23 WebInspector.CPUProfileNode.prototype = {
24 __proto__: WebInspector.ProfileNode.prototype
25 }
26 5
27 /** 6 /**
28 * @constructor 7 * @constructor
29 * @extends {WebInspector.ProfileTreeModel}
30 * @param {!ProfilerAgent.CPUProfile} profile 8 * @param {!ProfilerAgent.CPUProfile} profile
31 */ 9 */
32 WebInspector.CPUProfileDataModel = function(profile) 10 WebInspector.CPUProfileDataModel = function(profile)
33 { 11 {
12 this.profileHead = profile.head;
34 this.samples = profile.samples; 13 this.samples = profile.samples;
35 this.timestamps = profile.timestamps; 14 this.timestamps = profile.timestamps;
36 // Convert times from sec to msec.
37 this.profileStartTime = profile.startTime * 1000; 15 this.profileStartTime = profile.startTime * 1000;
38 this.profileEndTime = profile.endTime * 1000; 16 this.profileEndTime = profile.endTime * 1000;
39 this.totalHitCount = 0; 17 this._assignParentsInProfile();
40 if (!WebInspector.moduleSetting("showNativeFunctionsInJSProfile").get())
41 this._filterNativeFrames(profile.head);
42 this.profileHead = this._translateProfileTree(profile.head);
43 WebInspector.ProfileTreeModel.call(this, this.profileHead, this.profileStart Time, this.profileEndTime);
44 this._extractMetaNodes();
45 if (this.samples) { 18 if (this.samples) {
46 this._buildIdToNodeMap();
47 this._sortSamples(); 19 this._sortSamples();
48 this._normalizeTimestamps(); 20 this._normalizeTimestamps();
21 this._buildIdToNodeMap();
49 this._fixMissingSamples(); 22 this._fixMissingSamples();
50 } 23 }
51 this._assignTotalTimes(this.profileHead); 24 if (!WebInspector.moduleSetting("showNativeFunctionsInJSProfile").get())
25 this._filterNativeFrames();
26 this._assignDepthsInProfile();
27 this._calculateTimes(profile);
52 } 28 }
53 29
54 WebInspector.CPUProfileDataModel.prototype = { 30 WebInspector.CPUProfileDataModel.prototype = {
55 /** 31 /**
56 * @param {!ProfilerAgent.CPUProfileNode} root 32 * @param {!ProfilerAgent.CPUProfile} profile
57 */ 33 */
58 _filterNativeFrames: function(root) 34 _calculateTimes: function(profile)
59 { 35 {
60 // TODO: get rid of this function and do the filtering while _translateP rofileTree 36 function totalHitCount(node) {
37 var result = node.hitCount;
38 for (var i = 0; i < node.children.length; i++)
39 result += totalHitCount(node.children[i]);
40 return result;
41 }
42 profile.totalHitCount = totalHitCount(profile.head);
43 this.totalHitCount = profile.totalHitCount;
44
45 var duration = this.profileEndTime - this.profileStartTime;
46 var samplingInterval = duration / profile.totalHitCount;
47 this.samplingInterval = samplingInterval;
48
49 function calculateTimesForNode(node) {
50 node.selfTime = node.hitCount * samplingInterval;
51 var totalHitCount = node.hitCount;
52 for (var i = 0; i < node.children.length; i++)
53 totalHitCount += calculateTimesForNode(node.children[i]);
54 node.totalTime = totalHitCount * samplingInterval;
55 return totalHitCount;
56 }
57 calculateTimesForNode(profile.head);
58 },
59
60 _filterNativeFrames: function()
61 {
61 if (this.samples) { 62 if (this.samples) {
62 /** @type {!Map<number, !ProfilerAgent.CPUProfileNode>} */
63 var idToNode = new Map();
64 var stack = [root];
65 while (stack.length) {
66 var node = stack.pop();
67 idToNode.set(node.id, node);
68 for (var i = 0; i < node.children.length; i++) {
69 node.children[i].parent = node;
70 stack.push(node.children[i]);
71 }
72 }
73 for (var i = 0; i < this.samples.length; ++i) { 63 for (var i = 0; i < this.samples.length; ++i) {
74 var node = idToNode.get(this.samples[i]); 64 var node = this.nodeByIndex(i);
75 while (isNativeNode(node)) 65 while (isNativeNode(node))
76 node = node.parent; 66 node = node.parent;
77 this.samples[i] = node.id; 67 this.samples[i] = node.id;
78 } 68 }
79 } 69 }
80 processSubtree(root); 70 processSubtree(this.profileHead);
81 71
82 /** 72 /**
83 * @param {!ProfilerAgent.CPUProfileNode} node 73 * @param {!ProfilerAgent.CPUProfileNode} node
84 * @return {boolean} 74 * @return {boolean}
85 */ 75 */
86 function isNativeNode(node) 76 function isNativeNode(node)
87 { 77 {
88 return !!node.url && node.url.startsWith("native "); 78 return !!node.url && node.url.startsWith("native ");
89 } 79 }
90 80
(...skipping 30 matching lines...) Expand all
121 mergeChildren(node, child); 111 mergeChildren(node, child);
122 } else { 112 } else {
123 node.children.push(child); 113 node.children.push(child);
124 child.parent = node; 114 child.parent = node;
125 processSubtree(child); 115 processSubtree(child);
126 } 116 }
127 } 117 }
128 } 118 }
129 }, 119 },
130 120
131 /** 121 _assignParentsInProfile: function()
132 * @param {!ProfilerAgent.CPUProfileNode} root
133 * @return {!WebInspector.CPUProfileNode}
134 */
135 _translateProfileTree: function(root)
136 { 122 {
137 /** 123 var head = this.profileHead;
138 * @param {!ProfilerAgent.CPUProfileNode} node 124 head.parent = null;
139 * @return {number} 125 var nodesToTraverse = [ head ];
140 */ 126 while (nodesToTraverse.length) {
141 function computeHitCountForSubtree(node) 127 var parent = nodesToTraverse.pop();
142 { 128 var children = parent.children;
143 return node.children.reduce((acc, node) => acc + computeHitCountForS ubtree(node), node.hitCount); 129 var length = children.length;
130 for (var i = 0; i < length; ++i) {
131 var child = children[i];
132 child.parent = parent;
133 if (child.children.length)
134 nodesToTraverse.push(child);
135 }
144 } 136 }
145 this.totalHitCount = computeHitCountForSubtree(root);
146 var sampleTime = (this.profileEndTime - this.profileStartTime) / this.to talHitCount;
147 var resultRoot = new WebInspector.CPUProfileNode(root, sampleTime);
148 var targetNodeStack = [resultRoot];
149 var sourceNodeStack = [root];
150 while (sourceNodeStack.length) {
151 var sourceNode = sourceNodeStack.pop();
152 var parentNode = targetNodeStack.pop();
153 parentNode.children = sourceNode.children.map(child => new WebInspec tor.CPUProfileNode(child, sampleTime));
154 sourceNodeStack.push.apply(sourceNodeStack, sourceNode.children);
155 targetNodeStack.push.apply(targetNodeStack, parentNode.children);
156 }
157 return resultRoot;
158 }, 137 },
159 138
160 /** 139 _assignDepthsInProfile: function()
161 * @param {!WebInspector.ProfileNode} node
162 */
163 _assignTotalTimes: function(node)
164 { 140 {
165 // TODO: get rid of this field in favor of this.total 141 var head = this.profileHead;
166 node.totalTime = node.total; 142 head.depth = -1;
167 node.children.forEach(this._assignTotalTimes, this); 143 this.maxDepth = 0;
144 var nodesToTraverse = [ head ];
145 while (nodesToTraverse.length) {
146 var parent = nodesToTraverse.pop();
147 var depth = parent.depth + 1;
148 if (depth > this.maxDepth)
149 this.maxDepth = depth;
150 var children = parent.children;
151 var length = children.length;
152 for (var i = 0; i < length; ++i) {
153 var child = children[i];
154 child.depth = depth;
155 if (child.children.length)
156 nodesToTraverse.push(child);
157 }
158 }
168 }, 159 },
169 160
170 _sortSamples: function() 161 _sortSamples: function()
171 { 162 {
172 var timestamps = this.timestamps; 163 var timestamps = this.timestamps;
173 if (!timestamps) 164 if (!timestamps)
174 return; 165 return;
175 var samples = this.samples; 166 var samples = this.samples;
176 var indices = timestamps.map((x, index) => index); 167 var indices = timestamps.map((x, index) => index);
177 indices.sort((a, b) => timestamps[a] - timestamps[b]); 168 indices.sort((a, b) => timestamps[a] - timestamps[b]);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 timestamps[i] /= 1000; 206 timestamps[i] /= 1000;
216 var averageSample = (timestamps.peekLast() - timestamps[0]) / (timestamp s.length - 1); 207 var averageSample = (timestamps.peekLast() - timestamps[0]) / (timestamp s.length - 1);
217 // Add an extra timestamp used to calculate the last sample duration. 208 // Add an extra timestamp used to calculate the last sample duration.
218 this.timestamps.push(timestamps.peekLast() + averageSample); 209 this.timestamps.push(timestamps.peekLast() + averageSample);
219 this.profileStartTime = timestamps[0]; 210 this.profileStartTime = timestamps[0];
220 this.profileEndTime = timestamps.peekLast(); 211 this.profileEndTime = timestamps.peekLast();
221 }, 212 },
222 213
223 _buildIdToNodeMap: function() 214 _buildIdToNodeMap: function()
224 { 215 {
225 /** @type {!Object<number, !WebInspector.CPUProfileNode>} */ 216 /** @type {!Object.<number, !ProfilerAgent.CPUProfileNode>} */
226 this._idToNode = {}; 217 this._idToNode = {};
227 var idToNode = this._idToNode; 218 var idToNode = this._idToNode;
228 var stack = [this.profileHead]; 219 var stack = [this.profileHead];
229 while (stack.length) { 220 while (stack.length) {
230 var node = stack.pop(); 221 var node = stack.pop();
231 idToNode[node.id] = node; 222 idToNode[node.id] = node;
232 for (var i = 0; i < node.children.length; i++) 223 for (var i = 0; i < node.children.length; i++)
233 stack.push(node.children[i]); 224 stack.push(node.children[i]);
234 } 225 }
235 },
236 226
237 _extractMetaNodes: function()
238 {
239 var topLevelNodes = this.profileHead.children; 227 var topLevelNodes = this.profileHead.children;
240 for (var i = 0; i < topLevelNodes.length && !(this.gcNode && this.progra mNode && this.idleNode); i++) { 228 for (var i = 0; i < topLevelNodes.length && !(this.gcNode && this.progra mNode && this.idleNode); i++) {
241 var node = topLevelNodes[i]; 229 var node = topLevelNodes[i];
242 if (node.functionName === "(garbage collector)") 230 if (node.functionName === "(garbage collector)")
243 this.gcNode = node; 231 this.gcNode = node;
244 else if (node.functionName === "(program)") 232 else if (node.functionName === "(program)")
245 this.programNode = node; 233 this.programNode = node;
246 else if (node.functionName === "(idle)") 234 else if (node.functionName === "(idle)")
247 this.idleNode = node; 235 this.idleNode = node;
248 } 236 }
(...skipping 21 matching lines...) Expand all
270 var nextNodeId = samples[sampleIndex + 1]; 258 var nextNodeId = samples[sampleIndex + 1];
271 if (nodeId === programNodeId && !isSystemNode(prevNodeId) && !isSyst emNode(nextNodeId) 259 if (nodeId === programNodeId && !isSystemNode(prevNodeId) && !isSyst emNode(nextNodeId)
272 && bottomNode(idToNode[prevNodeId]) === bottomNode(idToNode[next NodeId])) { 260 && bottomNode(idToNode[prevNodeId]) === bottomNode(idToNode[next NodeId])) {
273 samples[sampleIndex] = prevNodeId; 261 samples[sampleIndex] = prevNodeId;
274 } 262 }
275 prevNodeId = nodeId; 263 prevNodeId = nodeId;
276 nodeId = nextNodeId; 264 nodeId = nextNodeId;
277 } 265 }
278 266
279 /** 267 /**
280 * @param {!WebInspector.ProfileNode} node 268 * @param {!ProfilerAgent.CPUProfileNode} node
281 * @return {!WebInspector.ProfileNode} 269 * @return {!ProfilerAgent.CPUProfileNode}
282 */ 270 */
283 function bottomNode(node) 271 function bottomNode(node)
284 { 272 {
285 while (node.parent.parent) 273 while (node.parent.parent)
286 node = node.parent; 274 node = node.parent;
287 return node; 275 return node;
288 } 276 }
289 277
290 /** 278 /**
291 * @param {number} nodeId 279 * @param {number} nodeId
292 * @return {boolean} 280 * @return {boolean}
293 */ 281 */
294 function isSystemNode(nodeId) 282 function isSystemNode(nodeId)
295 { 283 {
296 return nodeId === programNodeId || nodeId === gcNodeId || nodeId === idleNodeId; 284 return nodeId === programNodeId || nodeId === gcNodeId || nodeId === idleNodeId;
297 } 285 }
298 }, 286 },
299 287
300 /** 288 /**
301 * @param {function(number, !WebInspector.CPUProfileNode, number)} openFrame Callback 289 * @param {function(number, !ProfilerAgent.CPUProfileNode, number)} openFram eCallback
302 * @param {function(number, !WebInspector.CPUProfileNode, number, number, nu mber)} closeFrameCallback 290 * @param {function(number, !ProfilerAgent.CPUProfileNode, number, number, n umber)} closeFrameCallback
303 * @param {number=} startTime 291 * @param {number=} startTime
304 * @param {number=} stopTime 292 * @param {number=} stopTime
305 */ 293 */
306 forEachFrame: function(openFrameCallback, closeFrameCallback, startTime, sto pTime) 294 forEachFrame: function(openFrameCallback, closeFrameCallback, startTime, sto pTime)
307 { 295 {
308 if (!this.profileHead) 296 if (!this.profileHead)
309 return; 297 return;
310 298
311 startTime = startTime || 0; 299 startTime = startTime || 0;
312 stopTime = stopTime || Infinity; 300 stopTime = stopTime || Infinity;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 while (node.depth > prevNode.depth) { 351 while (node.depth > prevNode.depth) {
364 stackNodes.push(node); 352 stackNodes.push(node);
365 node = node.parent; 353 node = node.parent;
366 } 354 }
367 355
368 // Go down to the LCA and close current intervals. 356 // Go down to the LCA and close current intervals.
369 while (prevNode !== node) { 357 while (prevNode !== node) {
370 var start = stackStartTimes[stackTop]; 358 var start = stackStartTimes[stackTop];
371 var duration = sampleTime - start; 359 var duration = sampleTime - start;
372 stackChildrenDuration[stackTop - 1] += duration; 360 stackChildrenDuration[stackTop - 1] += duration;
373 closeFrameCallback(prevNode.depth, /** @type {!WebInspector.CPUP rofileNode} */(prevNode), start, duration, duration - stackChildrenDuration[stac kTop]); 361 closeFrameCallback(prevNode.depth, prevNode, start, duration, du ration - stackChildrenDuration[stackTop]);
374 --stackTop; 362 --stackTop;
375 if (node.depth === prevNode.depth) { 363 if (node.depth === prevNode.depth) {
376 stackNodes.push(node); 364 stackNodes.push(node);
377 node = node.parent; 365 node = node.parent;
378 } 366 }
379 prevNode = prevNode.parent; 367 prevNode = prevNode.parent;
380 } 368 }
381 369
382 // Go up the nodes stack and open new intervals. 370 // Go up the nodes stack and open new intervals.
383 while (stackNodes.length) { 371 while (stackNodes.length) {
(...skipping 11 matching lines...) Expand all
395 var duration = sampleTime - start; 383 var duration = sampleTime - start;
396 stackChildrenDuration[stackTop - 1] += duration; 384 stackChildrenDuration[stackTop - 1] += duration;
397 closeFrameCallback(gcParentNode.depth + 1, node, start, duration, du ration - stackChildrenDuration[stackTop]); 385 closeFrameCallback(gcParentNode.depth + 1, node, start, duration, du ration - stackChildrenDuration[stackTop]);
398 --stackTop; 386 --stackTop;
399 } 387 }
400 388
401 for (var node = idToNode[prevId]; node.parent; node = node.parent) { 389 for (var node = idToNode[prevId]; node.parent; node = node.parent) {
402 var start = stackStartTimes[stackTop]; 390 var start = stackStartTimes[stackTop];
403 var duration = sampleTime - start; 391 var duration = sampleTime - start;
404 stackChildrenDuration[stackTop - 1] += duration; 392 stackChildrenDuration[stackTop - 1] += duration;
405 closeFrameCallback(node.depth, /** @type {!WebInspector.CPUProfileNo de} */(node), start, duration, duration - stackChildrenDuration[stackTop]); 393 closeFrameCallback(node.depth, node, start, duration, duration - sta ckChildrenDuration[stackTop]);
406 --stackTop; 394 --stackTop;
407 } 395 }
408 }, 396 },
409 397
410 /** 398 /**
411 * @param {number} index 399 * @param {number} index
412 * @return {!WebInspector.CPUProfileNode} 400 * @return {!ProfilerAgent.CPUProfileNode}
413 */ 401 */
414 nodeByIndex: function(index) 402 nodeByIndex: function(index)
415 { 403 {
416 return this._idToNode[this.samples[index]]; 404 return this._idToNode[this.samples[index]];
417 }, 405 }
418 406
419 __proto__: WebInspector.ProfileTreeModel.prototype
420 } 407 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/devtools.gypi ('k') | third_party/WebKit/Source/devtools/front_end/sdk/ProfileTreeModel.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698