OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <!-- | |
3 Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
4 Use of this source code is governed by a BSD-style license that can be | |
5 found in the LICENSE file. | |
6 --> | |
7 <link rel="import" href="/perf_insights/mappers/reduce.html"> | |
8 <link rel="import" href="/tracing/extras/ads/domain_category.html"> | |
9 <link rel="import" href="/tracing/extras/chrome/slice_title_fixer.html"> | |
10 <link rel="import" href="/tracing/model/source_info/js_source_info.html"> | |
11 | |
12 <script> | |
13 'use strict'; | |
14 | |
15 tr.exportTo('pi.m', function() { | |
16 var JSSourceState = tr.model.source_info.JSSourceState; | |
17 | |
18 function SliceCostInfo() { | |
19 this.threadGroup = undefined; | |
20 this.railTypeName = undefined; | |
21 this.title = undefined; | |
22 this.domainCategory = undefined; | |
23 this.domain = undefined; | |
24 this.userFriendlyCategory = undefined; | |
25 | |
26 this.selfTime = 0; | |
27 this.cpuSelfTime = 0; | |
28 | |
29 this.jsTime = 0; | |
30 this.jsTimeByState = {}; | |
31 for (var state in JSSourceState) { | |
32 this.jsTimeByState[JSSourceState[state]] = 0; | |
33 } | |
34 this.data = {}; | |
35 } | |
36 | |
37 SliceCostInfo.asReduceTarget = function(key, firstValue) { | |
38 var sliceCostInfo = new SliceCostInfo(); | |
39 sliceCostInfo.threadGroup = firstValue.threadGroup; | |
40 sliceCostInfo.railTypeName = firstValue.railTypeName; | |
41 sliceCostInfo.title = firstValue.title; | |
42 sliceCostInfo.domainCategory = firstValue.domainCategory; | |
43 sliceCostInfo.domain = firstValue.domain; | |
44 sliceCostInfo.userFriendlyCategory = firstValue.userFriendlyCategory; | |
45 sliceCostInfo.data = firstValue.data; | |
46 return sliceCostInfo; | |
47 }; | |
48 | |
49 SliceCostInfo.fromDict = function(d) { | |
50 var sliceCostInfo = new SliceCostInfo(); | |
51 sliceCostInfo.threadGroup = d.threadGroup; | |
52 sliceCostInfo.railTypeName = d.railTypeName; | |
53 sliceCostInfo.title = d.title; | |
54 sliceCostInfo.domainCategory = d.domainCategory; | |
55 sliceCostInfo.domain = d.domain; | |
56 sliceCostInfo.userFriendlyCategory = d.userFriendlyCategory; | |
57 sliceCostInfo.selfTime = d.selfTime; | |
58 sliceCostInfo.cpuSelfTime = d.cpuSelfTime; | |
59 sliceCostInfo.jsTime = d.jsTime || 0; | |
60 for (var state in JSSourceState) { | |
61 if (d.jsTimeByState === undefined) { | |
62 sliceCostInfo.jsTimeByState[state] = 0; | |
63 } else { | |
64 sliceCostInfo.jsTimeByState[JSSourceState[state]] = | |
65 d.jsTimeByState[JSSourceState[state]] || 0; | |
66 } | |
67 } | |
68 sliceCostInfo.data = d.data; | |
69 return sliceCostInfo; | |
70 }; | |
71 | |
72 SliceCostInfo.prototype = { | |
73 push: function(sliceCostKey, threadSlice) { | |
74 if (threadSlice.selfTime !== undefined) | |
75 this.selfTime += threadSlice.selfTime; | |
76 if (threadSlice.cpuSelfTime !== undefined) | |
77 this.cpuSelfTime += threadSlice.cpuSelfTime; | |
78 if (threadSlice.jsTime !== undefined) | |
79 this.jsTime += threadSlice.jsTime; | |
80 if (threadSlice.jsTimeByState !== undefined) { | |
81 for (var state in JSSourceState) { | |
82 this.jsTimeByState[JSSourceState[state]] += | |
83 threadSlice.jsTimeByState[JSSourceState[state]]; | |
84 } | |
85 } | |
86 }, | |
87 | |
88 finalizeAndGetResult: function() { | |
89 return this; | |
90 } | |
91 }; | |
92 | |
93 | |
94 function getSliceCostReport(model, threadGrouping, railTypeNameByGUID, | |
95 filterFunction, dataCB) { | |
96 var reduce = new pi.m.StreamingReducer(SliceCostInfo.asReduceTarget); | |
97 | |
98 function generateDomainCosts(slice) { | |
99 // V8.Execute events may generate several sliceCostInfo, based on the | |
100 // origin of the JS being executed. | |
101 var range = new tr.b.Range(); | |
102 slice.addBoundsToRange(range); | |
103 var filtered = range.filterArray( | |
104 slice.parentContainer.samples, | |
105 function(sample) {return sample.start;}); | |
106 filtered.forEach(function(sample) { | |
107 var sliceCostInfo = new SliceCostInfo(); | |
108 sliceCostInfo.threadGroup = threadGrouping.getGroupNameForEvent(slice); | |
109 sliceCostInfo.railTypeName = railTypeNameByGUID[slice.guid]; | |
110 | |
111 var ufc = model.getUserFriendlyCategoryFromEvent(slice); | |
112 sliceCostInfo.userFriendlyCategory = ufc || 'other'; | |
113 sliceCostInfo.title = tr.e.chrome.SliceTitleFixer.fromEvent(slice); | |
114 sliceCostInfo.domain = sample.leafStackFrame.domain; | |
115 sliceCostInfo.domainCategory = | |
116 tr.e.ads.DomainCategory.fromDomain(sliceCostInfo.domain); | |
117 sliceCostInfo.selfTime = sample.weight; | |
118 sliceCostInfo.cpuSelfTime = sample.weight; | |
119 if (dataCB !== undefined) | |
120 sliceCostInfo.data = dataCB(slice); | |
121 // Let's use the state of the leaf frame. TODO(chiniforooshan): | |
122 // understand what it means if frames of a sample stack are in different | |
123 // states (BUG #1542). | |
124 var sourceInfo = sample.leafStackFrame.sourceInfo; | |
125 if (sourceInfo === undefined || | |
126 !(sourceInfo instanceof tr.model.source_info.JSSourceInfo)) { | |
127 sliceCostInfo.jsTime = sample.weight; | |
128 sliceCostInfo.jsTimeByState[JSSourceState.UNKNOWN] = sample.weight; | |
129 } else { | |
130 sliceCostInfo.jsTimeByState[sourceInfo.state] = sample.weight; | |
131 } | |
132 var key = sliceCostInfo.threadGroup + '/' + | |
133 sliceCostInfo.railTypeName + '/' + | |
134 sliceCostInfo.title + '/' + | |
135 sliceCostInfo.domain; | |
136 reduce.push(key, sliceCostInfo); | |
137 }); | |
138 } | |
139 | |
140 model.iterateAllEvents(function(event) { | |
141 if (!(event instanceof tr.model.ThreadSlice)) | |
142 return; | |
143 if (filterFunction && !filterFunction(event)) | |
144 return; | |
145 | |
146 var threadSlice = event; | |
147 if (threadSlice.title === 'V8.Execute') { | |
148 generateDomainCosts(threadSlice); | |
149 return; | |
150 } | |
151 | |
152 var sliceCostInfo = new SliceCostInfo(); | |
153 sliceCostInfo.threadGroup = threadGrouping.getGroupNameForEvent( | |
154 threadSlice); | |
155 sliceCostInfo.railTypeName = railTypeNameByGUID[threadSlice.guid]; | |
156 var ufc = model.getUserFriendlyCategoryFromEvent(threadSlice); | |
157 sliceCostInfo.userFriendlyCategory = ufc || 'other'; | |
158 sliceCostInfo.title = tr.e.chrome.SliceTitleFixer.fromEvent(threadSlice); | |
159 // For all other events, just generate one sliceCostInfo. | |
160 sliceCostInfo.selfTime = threadSlice.selfTime; | |
161 sliceCostInfo.cpuSelfTime = threadSlice.cpuSelfTime; | |
162 if (dataCB !== undefined) | |
163 sliceCostInfo.data = dataCB(event); | |
164 | |
165 var key = sliceCostInfo.threadGroup + '/' + | |
166 sliceCostInfo.railTypeName + '/' + | |
167 sliceCostInfo.title; | |
168 reduce.push(key, sliceCostInfo); | |
169 }); | |
170 | |
171 var sliceCostInfos = []; | |
172 reduce.finalizeAndIterResults(function(key, sliceCostInfo) { | |
173 sliceCostInfos.push(sliceCostInfo); | |
174 }); | |
175 return sliceCostInfos; | |
176 } | |
177 | |
178 return { | |
179 SliceCostInfo: SliceCostInfo, | |
180 | |
181 getSliceCostReport: getSliceCostReport | |
182 }; | |
183 }); | |
184 </script> | |
OLD | NEW |