Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / system_stats / system_stats_instance_track.html
1 <!DOCTYPE html>
2 <!--
3 Copyright (c) 2013 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
8 <link rel="stylesheet" href="/system_stats/system_stats_instance_track.css">
9 <link rel="import" href="/tvcm/sorted_array_utils.html">
10 <link rel="import" href="/tracing/tracks/stacked_bars_track.html">
11 <link rel="import" href="/tracing/tracks/object_instance_track.html">
12 <link rel="import" href="/tracing/color_scheme.html">
13 <link rel="import" href="/tvcm/ui.html">
14
15 <script>
16 'use strict';
17
18 tvcm.exportTo('system_stats', function() {
19   var EventPresenter = tracing.EventPresenter;
20
21   var palette = tvcm.ui.getColorPalette();
22   var highlightIdBoost = tvcm.ui.getColorPaletteHighlightIdBoost();
23
24   var statCount;
25
26   var excludedStats = {'meminfo': {
27                         'pswpin': 0,
28                         'pswpout': 0,
29                         'pgmajfault': 0},
30                       'diskinfo': {
31                         'io': 0,
32                         'io_time': 0,
33                         'read_time': 0,
34                         'reads': 0,
35                         'reads_merged': 0,
36                         'sectors_read': 0,
37                         'sectors_written': 0,
38                         'weighted_io_time': 0,
39                         'write_time': 0,
40                         'writes': 0,
41                         'writes_merged': 0},
42                       'swapinfo': {}
43                       };
44
45   /**
46    * Tracks that display system stats data.
47    *
48    * @constructor
49    * @extends {StackedBarsTrack}
50    */
51
52   var SystemStatsInstanceTrack = tvcm.ui.define(
53       'system-stats-instance-track', tracing.tracks.StackedBarsTrack);
54
55   SystemStatsInstanceTrack.prototype = {
56
57     __proto__: tracing.tracks.StackedBarsTrack.prototype,
58
59     decorate: function(viewport) {
60       tracing.tracks.StackedBarsTrack.prototype.decorate.call(this, viewport);
61       this.classList.add('system-stats-instance-track');
62       this.objectInstance_ = null;
63     },
64
65     set objectInstances(objectInstances) {
66       if (!objectInstances) {
67         this.objectInstance_ = [];
68         return;
69       }
70       if (objectInstances.length != 1)
71         throw new Error('Bad object instance count.');
72       this.objectInstance_ = objectInstances[0];
73       if (this.objectInstance_ !== null) {
74         this.computeRates_(this.objectInstance_.snapshots);
75         this.maxStats_ = this.computeMaxStats_(
76             this.objectInstance_.snapshots);
77       }
78     },
79
80     computeRates_: function(snapshots) {
81       for (var i = 0; i < snapshots.length; i++) {
82         var snapshot = snapshots[i];
83         var stats = snapshot.getStats();
84         var prevSnapshot;
85         var prevStats;
86
87         if (i == 0) {
88           // Deltas will be zero.
89           prevSnapshot = snapshots[0];
90         } else {
91           prevSnapshot = snapshots[i - 1];
92         }
93         prevStats = prevSnapshot.getStats();
94         var timeIntervalSeconds = (snapshot.ts - prevSnapshot.ts) / 1000;
95         // Prevent divide by zero.
96         if (timeIntervalSeconds == 0)
97           timeIntervalSeconds = 1;
98
99         this.computeRatesRecursive_(prevStats, stats,
100                                     timeIntervalSeconds);
101       }
102     },
103
104     computeRatesRecursive_: function(prevStats, stats,
105                                      timeIntervalSeconds) {
106       for (var statName in stats) {
107         if (stats[statName] instanceof Object) {
108           this.computeRatesRecursive_(prevStats[statName],
109                                       stats[statName],
110                                       timeIntervalSeconds);
111         } else {
112           if (statName == 'sectors_read') {
113             stats['bytes_read_per_sec'] = (stats['sectors_read'] -
114                                            prevStats['sectors_read']) *
115                                           512 / timeIntervalSeconds;
116           }
117           if (statName == 'sectors_written') {
118             stats['bytes_written_per_sec'] =
119                 (stats['sectors_written'] -
120                  prevStats['sectors_written']) *
121                 512 / timeIntervalSeconds;
122           }
123           if (statName == 'pgmajfault') {
124             stats['pgmajfault_per_sec'] = (stats['pgmajfault'] -
125                                            prevStats['pgmajfault']) /
126                                           timeIntervalSeconds;
127           }
128           if (statName == 'pswpin') {
129             stats['bytes_swpin_per_sec'] = (stats['pswpin'] -
130                                             prevStats['pswpin']) *
131                                            1000 / timeIntervalSeconds;
132           }
133           if (statName == 'pswpout') {
134             stats['bytes_swpout_per_sec'] = (stats['pswpout'] -
135                                              prevStats['pswpout']) *
136                                             1000 / timeIntervalSeconds;
137           }
138         }
139       }
140     },
141
142     computeMaxStats_: function(snapshots) {
143       var maxStats = new Object();
144       statCount = 0;
145
146       for (var i = 0; i < snapshots.length; i++) {
147         var snapshot = snapshots[i];
148         var stats = snapshot.getStats();
149
150         this.computeMaxStatsRecursive_(stats, maxStats,
151                                        excludedStats);
152       }
153
154       return maxStats;
155     },
156
157     computeMaxStatsRecursive_: function(stats, maxStats, excludedStats) {
158       for (var statName in stats) {
159         if (stats[statName] instanceof Object) {
160           if (!(statName in maxStats))
161             maxStats[statName] = new Object();
162
163           var excludedNested;
164           if (excludedStats && statName in excludedStats)
165             excludedNested = excludedStats[statName];
166           else
167             excludedNested = null;
168
169           this.computeMaxStatsRecursive_(stats[statName],
170                                          maxStats[statName],
171                                          excludedNested);
172         } else {
173           if (excludedStats && statName in excludedStats)
174             continue;
175           if (!(statName in maxStats)) {
176             maxStats[statName] = 0;
177             statCount++;
178           }
179           if (stats[statName] > maxStats[statName])
180             maxStats[statName] = stats[statName];
181         }
182       }
183     },
184
185     get height() {
186       return window.getComputedStyle(this).height;
187     },
188
189     set height(height) {
190       this.style.height = height;
191     },
192
193     draw: function(type, viewLWorld, viewRWorld) {
194       switch (type) {
195         case tracing.tracks.DrawType.SLICE:
196           this.drawStatBars_(viewLWorld, viewRWorld);
197           break;
198       }
199     },
200
201     drawStatBars_: function(viewLWorld, viewRWorld) {
202       var ctx = this.context();
203       var pixelRatio = window.devicePixelRatio || 1;
204
205       var bounds = this.getBoundingClientRect();
206       var width = bounds.width * pixelRatio;
207       var height = (bounds.height * pixelRatio) / statCount;
208
209       // Culling parameters.
210       var vp = this.viewport.currentDisplayTransform;
211
212       // Scale by the size of the largest snapshot.
213       var maxStats = this.maxStats_;
214
215       var objectSnapshots = this.objectInstance_.snapshots;
216       var lowIndex = tvcm.findLowIndexInSortedArray(
217           objectSnapshots,
218           function(snapshot) {
219             return snapshot.ts;
220           },
221           viewLWorld);
222
223       // Assure that the stack with the left edge off screen still gets drawn
224       if (lowIndex > 0)
225         lowIndex -= 1;
226
227       for (var i = lowIndex; i < objectSnapshots.length; ++i) {
228         var snapshot = objectSnapshots[i];
229         var trace = snapshot.getStats();
230         var currentY = height;
231
232         var left = snapshot.ts;
233         if (left > viewRWorld)
234           break;
235         var leftView = vp.xWorldToView(left);
236         if (leftView < 0)
237           leftView = 0;
238
239         // Compute the edges for the column graph bar.
240         var right;
241         if (i != objectSnapshots.length - 1) {
242           right = objectSnapshots[i + 1].ts;
243         } else {
244           // If this is the last snaphot of multiple snapshots, use the width of
245           // the previous snapshot for the width.
246           if (objectSnapshots.length > 1)
247             right = objectSnapshots[i].ts + (objectSnapshots[i].ts -
248                     objectSnapshots[i - 1].ts);
249           else
250             // If there's only one snapshot, use max bounds as the width.
251             right = this.objectInstance_.parent.model.bounds.max;
252         }
253
254         var rightView = vp.xWorldToView(right);
255         if (rightView > width)
256           rightView = width;
257
258         // Floor the bounds to avoid a small gap between stacks.
259         leftView = Math.floor(leftView);
260         rightView = Math.floor(rightView);
261
262         // Descend into nested stats.
263         this.drawStatBarsRecursive_(snapshot,
264                                     leftView,
265                                     rightView,
266                                     height,
267                                     trace,
268                                     maxStats,
269                                     currentY);
270
271         if (i == lowIndex)
272           this.drawStatNames_(leftView, height, currentY, '', maxStats);
273       }
274       ctx.lineWidth = 1;
275     },
276
277     drawStatBarsRecursive_: function(snapshot,
278                                      leftView,
279                                      rightView,
280                                      height,
281                                      stats,
282                                      maxStats,
283                                      currentY) {
284       var ctx = this.context();
285
286       for (var statName in maxStats) {
287         if (stats[statName] instanceof Object) {
288           // Use the y-position returned from the recursive call.
289           currentY = this.drawStatBarsRecursive_(snapshot,
290                                                  leftView,
291                                                  rightView,
292                                                  height,
293                                                  stats[statName],
294                                                  maxStats[statName],
295                                                  currentY);
296         } else {
297           var maxStat = maxStats[statName];
298
299           // Draw a bar for the stat. The height of the bar is scaled
300           // against the largest value of the stat across all snapshots.
301           ctx.fillStyle = EventPresenter.getBarSnapshotColor(
302               snapshot, Math.round(currentY / height));
303
304           var barHeight;
305
306           if (maxStat > 0) {
307             barHeight = height * Math.max(stats[statName], 0) / maxStat;
308           } else {
309             barHeight = 0;
310           }
311
312           ctx.fillRect(leftView, currentY - barHeight,
313                        Math.max(rightView - leftView, 1), barHeight);
314
315           currentY += height;
316         }
317       }
318
319       // Return the updated y-position.
320       return currentY;
321     },
322
323     drawStatNames_: function(leftView, height, currentY, prefix, maxStats) {
324       var ctx = this.context();
325
326       ctx.textAlign = 'end';
327       ctx.font = '12px Arial';
328       ctx.fillStyle = '#000000';
329       for (var statName in maxStats) {
330         if (maxStats[statName] instanceof Object) {
331           currentY = this.drawStatNames_(leftView, height, currentY,
332                                          statName, maxStats[statName]);
333         } else {
334           var fullname = statName;
335
336           if (prefix != '')
337             fullname = prefix + ' :: ' + statName;
338
339           ctx.fillText(fullname, leftView - 10, currentY - height / 4);
340           currentY += height;
341         }
342       }
343
344       return currentY;
345     }
346   };
347
348   tracing.tracks.ObjectInstanceTrack.register(
349       'base::TraceEventSystemStatsMonitor::SystemStats',
350       SystemStatsInstanceTrack);
351
352   return {
353     SystemStatsInstanceTrack: SystemStatsInstanceTrack
354   };
355 });
356 </script>