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

Side by Side Diff: tools/deep_memory_profiler/visualizer/profiler.js

Issue 23777005: Modified directory preparing for app engine for dmprof visualizer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove index.js Created 7 years, 3 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
(Empty)
1 // Copyright 2013 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 /**
6 * This class provides data access interface for dump file profiler.
7 * @constructor
8 */
9 var Profiler = function(jsonData) {
10 this.jsonData_ = jsonData;
11 // Initialize template with templates information.
12 this.template_ = jsonData.templates['l2'];
13 // Initialize selected category, and nothing selected at first.
14 this.selected_ = null;
15
16 // Trigger event.
17 this.callbacks_ = {};
18 };
19
20 /**
21 * Mimic Eventemitter in node. Add new listener for event.
22 * @param {string} event
23 * @param {Function} callback
24 */
25 Profiler.prototype.addListener = function(event, callback) {
26 if (!this.callbacks_[event])
27 this.callbacks_[event] = $.Callbacks();
28 this.callbacks_[event].add(callback);
29 };
30
31 /**
32 * This function will emit the event.
33 * @param {string} event
34 */
35 Profiler.prototype.emit = function(event) {
36 // Listeners should be able to receive arbitrary number of parameters.
37 var eventArguments = Array.prototype.slice.call(arguments, 1);
38
39 if (this.callbacks_[event])
40 this.callbacks_[event].fire.apply(this, eventArguments);
41 };
42
43 /**
44 * Remove listener from event.
45 * @param {string} event
46 * @param {Function} callback
47 */
48 Profiler.prototype.removeListener = function(event, callback) {
49 if (this.callbacks_[event])
50 this.callbacks_[event].remove(callback);
51 };
52
53 /**
54 * Calcualte initial models according default template.
55 */
56 Profiler.prototype.reparse = function() {
57 this.models_ = this.parseTemplate_();
58 this.emit('changed', this.models_);
59 };
60
61 /**
62 * To be called by view when new model being selected.
63 * And then triggers all relative views to update.
64 */
65 Profiler.prototype.setSelected = function(id) {
66 this.selected_ = id;
67 this.emit('changed:selected', id);
68 };
69
70 /**
71 * Get all models throughout the whole timeline of given id.
72 * @param {string} id Model id.
73 * @return {Array.<Object>} model array of given id.
74 */
75 Profiler.prototype.getModelsbyId = function(id) {
76 function find(model) {
77 if (model.id === id)
78 return model;
79 if ('children' in model)
80 return model.children.reduce(function(previous, current) {
81 var matched = find(current);
82 if (matched)
83 previous = matched;
84 return previous;
85 }, null);
86 }
87
88 return this.models_.reduce(function(previous, current) {
89 var matched = find(current);
90 if (matched)
91 previous.push(matched);
92 return previous;
93 }, []);
94 };
95
96 /**
97 * Get current sub of given model, return undefined if sub dont exist.
98 * @param {string} id Model id.
99 * @return {undefined|string} world-breakdown like 'vm-map'.
100 */
101 Profiler.prototype.getCurSubById = function(id) {
102 // Root won't has breakdown.
103 var path = id.split(',').splice(1);
104 if (!path.length) return null;
105
106 var tmpl = this.template_;
107 var curSub = path.reduce(function(previous, current, index) {
108 return previous[2][current];
109 }, tmpl);
110
111 // return
112 return curSub && curSub[0] + ',' + curSub[1];
113 };
114
115 /**
116 * Generate and then reparse new template when new sub was selected.
117 * @param {string|null} sub World-breakdown like 'vm-map'.
118 */
119 Profiler.prototype.setSub = function(sub) {
120 var selected = this.selected_;
121 var path = selected.split(',');
122 var key = path[path.length-1];
123
124 // Add sub breakdown to template.
125 var models = this.getModelsbyId(selected);
126 var subTmpl = sub.split(',');
127 subTmpl.push({});
128 models[0].template[2][key] = subTmpl;
129
130 // Recalculate new template.
131 this.reparse();
132 };
133
134 /**
135 * Calculate the model of certain snapshot.
136 * @param {string} template Local template.
137 * @param {Object} snapshot Current snapshot.
138 * @param {Object} worldUnits Mapping of world units.
139 * @param {Array.<number>} localUnits Array of local units.
140 * @param {string} name Local node path.
141 * @return {Object} Return model, total size and remaining units.
142 * @private
143 */
144 Profiler.prototype.accumulate_ = function(
145 template, snapshot, worldUnits, localUnits, name) {
146 var self = this;
147 var totalSize = 0;
148 var worldName = template[0];
149 var breakdownName = template[1];
150 var categories = snapshot.worlds[worldName].breakdown[breakdownName];
151 // Make deep copy of localUnits.
152 var remainderUnits = localUnits.slice(0);
153 var model = {
154 name: name || worldName + '-' + breakdownName,
155 children: []
156 };
157
158 Object.keys(categories).forEach(function(categoryName) {
159 var category = categories[categoryName];
160 if (category['hidden'] === true)
161 return;
162
163 // Filter units.
164 var matchedUnits = intersection(category.units, localUnits);
165 remainderUnits = difference(remainderUnits, matchedUnits);
166
167 // Accumulate categories.
168 var size = matchedUnits.reduce(function(previous, current) {
169 return previous + worldUnits[worldName][current];
170 }, 0);
171 totalSize += size;
172
173 // Handle subs options if exists.
174 var child = null;
175 if (!(categoryName in template[2])) {
176 // Calculate child for current category.
177 child = {
178 name: categoryName,
179 size: size
180 };
181 if ('subs' in category && category.subs.length) {
182 child.subs = category.subs;
183 child.template = template;
184 }
185
186 model.children.push(child);
187 } else {
188 // Calculate child recursively.
189 var subTemplate = template[2][categoryName];
190 var subWorldName = subTemplate[0];
191 var retVal = null;
192
193 if (subWorldName === worldName) {
194 // If subs is in the same world, units should be filtered.
195 retVal = self.accumulate_(subTemplate, snapshot, worldUnits,
196 matchedUnits, categoryName);
197 if ('subs' in category && category.subs.length) {
198 retVal.model.subs = category.subs;
199 retVal.model.template = template;
200 }
201 model.children.push(retVal.model);
202 // Don't output remaining item without any unit.
203 if (!retVal.remainderUnits.length)
204 return;
205
206 // Sum up remaining units size.
207 var remainSize =
208 retVal.remainderUnits.reduce(function(previous, current) {
209 return previous + worldUnits[subWorldName][current];
210 }, 0);
211
212 model.children.push({
213 name: categoryName + '-remaining',
214 size: remainSize
215 });
216 } else {
217 // If subs is in different world, use all units in that world.
218 var subLocalUnits = Object.keys(worldUnits[subWorldName]);
219 subLocalUnits = subLocalUnits.map(function(unitID) {
220 return parseInt(unitID, 10);
221 });
222
223 retVal = self.accumulate_(subTemplate, snapshot, worldUnits,
224 subLocalUnits, categoryName);
225 if ('subs' in category && category.subs.length) {
226 retVal.model.subs = category.subs;
227 retVal.model.template = template;
228 }
229 model.children.push(retVal.model);
230
231 if (size > retVal.totalSize) {
232 model.children.push({
233 name: categoryName + '-remaining',
234 size: size - retVal.totalSize
235 });
236 } else {
237 // Output WARNING when sub-breakdown size is larger.
238 console.log('WARNING: size of sub-breakdown is larger');
239 }
240 }
241 }
242 });
243
244 return {
245 model: model,
246 totalSize: totalSize,
247 remainderUnits: remainderUnits
248 };
249 };
250
251 /**
252 * Parse template and calculate models of the whole timeline.
253 * @return {Array.<Object>} Models of the whole timeline.
254 * @private
255 */
256 Profiler.prototype.parseTemplate_ = function() {
257 function calModelId(model, localPath) {
258 // Create unique id for every model.
259 model.id = localPath.length ?
260 localPath.join() + ',' + model.name : model.name;
261
262 if ('children' in model) {
263 model.children.forEach(function(child, index) {
264 var childPath = localPath.slice(0);
265 childPath.push(model.name);
266 calModelId(child, childPath);
267 });
268 }
269 }
270
271 var self = this;
272
273 return self.jsonData_.snapshots.map(function(snapshot) {
274 var worldUnits = {};
275 for (var worldName in snapshot.worlds) {
276 worldUnits[worldName] = {};
277 var units = snapshot.worlds[worldName].units;
278 for (var unitID in units)
279 worldUnits[worldName][unitID] = units[unitID][0];
280 }
281 var localUnits = Object.keys(worldUnits[self.template_[0]]);
282 localUnits = localUnits.map(function(unitID) {
283 return parseInt(unitID, 10);
284 });
285
286 var retVal =
287 self.accumulate_(self.template_, snapshot, worldUnits, localUnits);
288 calModelId(retVal.model, []);
289 return retVal.model;
290 });
291 };
OLDNEW
« no previous file with comments | « tools/deep_memory_profiler/visualizer/menu-view.js ('k') | tools/deep_memory_profiler/visualizer/profiler_unittest.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698