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

Side by Side Diff: netlog_viewer/timeline_data_series.js

Issue 2162963002: [polymer] Merge of master into polymer10-migration (Closed) Base URL: git@github.com:catapult-project/catapult.git@polymer10-migration
Patch Set: Merge polymer10-migration int polymer10-merge Created 4 years, 5 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
« no previous file with comments | « netlog_viewer/time_util.js ('k') | netlog_viewer/timeline_graph_view.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 * Different data types that each require their own labelled axis.
7 */
8 var TimelineDataType = {
9 SOURCE_COUNT: 0,
10 BYTES_PER_SECOND: 1
11 };
12
13 /**
14 * A TimelineDataSeries collects an ordered series of (time, value) pairs,
15 * and converts them to graph points. It also keeps track of its color and
16 * current visibility state. DataSeries are solely responsible for tracking
17 * data, and do not send notifications on state changes.
18 *
19 * Abstract class, doesn't implement onReceivedLogEntry.
20 */
21 var TimelineDataSeries = (function() {
22 'use strict';
23
24 /**
25 * @constructor
26 */
27 function TimelineDataSeries(dataType) {
28 // List of DataPoints in chronological order.
29 this.dataPoints_ = [];
30
31 // Data type of the DataSeries. This is used to scale all values with
32 // the same units in the same way.
33 this.dataType_ = dataType;
34 // Default color. Should always be overridden prior to display.
35 this.color_ = 'red';
36 // Whether or not the data series should be drawn.
37 this.isVisible_ = false;
38
39 this.cacheStartTime_ = null;
40 this.cacheStepSize_ = 0;
41 this.cacheValues_ = [];
42 }
43
44 TimelineDataSeries.prototype = {
45 /**
46 * Adds a DataPoint to |this| with the specified time and value.
47 * DataPoints are assumed to be received in chronological order.
48 */
49 addPoint: function(timeTicks, value) {
50 var time = timeutil.convertTimeTicksToDate(timeTicks).getTime();
51 this.dataPoints_.push(new DataPoint(time, value));
52 },
53
54 isVisible: function() {
55 return this.isVisible_;
56 },
57
58 show: function(isVisible) {
59 this.isVisible_ = isVisible;
60 },
61
62 getColor: function() {
63 return this.color_;
64 },
65
66 setColor: function(color) {
67 this.color_ = color;
68 },
69
70 getDataType: function() {
71 return this.dataType_;
72 },
73
74 /**
75 * Returns a list containing the values of the data series at |count|
76 * points, starting at |startTime|, and |stepSize| milliseconds apart.
77 * Caches values, so showing/hiding individual data series is fast, and
78 * derived data series can be efficiently computed, if we add any.
79 */
80 getValues: function(startTime, stepSize, count) {
81 // Use cached values, if we can.
82 if (this.cacheStartTime_ == startTime &&
83 this.cacheStepSize_ == stepSize &&
84 this.cacheValues_.length == count) {
85 return this.cacheValues_;
86 }
87
88 // Do all the work.
89 this.cacheValues_ = this.getValuesInternal_(startTime, stepSize, count);
90 this.cacheStartTime_ = startTime;
91 this.cacheStepSize_ = stepSize;
92
93 return this.cacheValues_;
94 },
95
96 /**
97 * Does all the work of getValues when we can't use cached data.
98 *
99 * The default implementation just uses the |value| of the most recently
100 * seen DataPoint before each time, but other DataSeries may use some
101 * form of interpolation.
102 * TODO(mmenke): Consider returning the maximum value over each interval
103 * to create graphs more stable with respect to zooming.
104 */
105 getValuesInternal_: function(startTime, stepSize, count) {
106 var values = [];
107 var nextPoint = 0;
108 var currentValue = 0;
109 var time = startTime;
110 for (var i = 0; i < count; ++i) {
111 while (nextPoint < this.dataPoints_.length &&
112 this.dataPoints_[nextPoint].time < time) {
113 currentValue = this.dataPoints_[nextPoint].value;
114 ++nextPoint;
115 }
116 values[i] = currentValue;
117 time += stepSize;
118 }
119 return values;
120 }
121 };
122
123 /**
124 * A single point in a data series. Each point has a time, in the form of
125 * milliseconds since the Unix epoch, and a numeric value.
126 * @constructor
127 */
128 function DataPoint(time, value) {
129 this.time = time;
130 this.value = value;
131 }
132
133 return TimelineDataSeries;
134 })();
135
136 /**
137 * Tracks how many sources of the given type have seen a begin
138 * event of type |eventType| more recently than an end event.
139 */
140 var SourceCountDataSeries = (function() {
141 'use strict';
142
143 var superClass = TimelineDataSeries;
144
145 /**
146 * @constructor
147 */
148 function SourceCountDataSeries(sourceType, eventType) {
149 superClass.call(this, TimelineDataType.SOURCE_COUNT);
150 this.sourceType_ = sourceType;
151 this.eventType_ = eventType;
152
153 // Map of sources for which we've seen a begin event more recently than an
154 // end event. Each such source has a value of "true". All others are
155 // undefined.
156 this.activeSources_ = {};
157 // Number of entries in |activeSources_|.
158 this.activeCount_ = 0;
159 }
160
161 SourceCountDataSeries.prototype = {
162 // Inherit the superclass's methods.
163 __proto__: superClass.prototype,
164
165 onReceivedLogEntry: function(entry) {
166 if (entry.source.type != this.sourceType_ ||
167 entry.type != this.eventType_) {
168 return;
169 }
170
171 if (entry.phase == EventPhase.PHASE_BEGIN) {
172 this.onBeginEvent(entry.source.id, entry.time);
173 return;
174 }
175 if (entry.phase == EventPhase.PHASE_END)
176 this.onEndEvent(entry.source.id, entry.time);
177 },
178
179 /**
180 * Called when the source with the specified id begins doing whatever we
181 * care about. If it's not already an active source, we add it to the map
182 * and add a data point.
183 */
184 onBeginEvent: function(id, time) {
185 if (this.activeSources_[id])
186 return;
187 this.activeSources_[id] = true;
188 ++this.activeCount_;
189 this.addPoint(time, this.activeCount_);
190 },
191
192 /**
193 * Called when the source with the specified id stops doing whatever we
194 * care about. If it's an active source, we remove it from the map and add
195 * a data point.
196 */
197 onEndEvent: function(id, time) {
198 if (!this.activeSources_[id])
199 return;
200 delete this.activeSources_[id];
201 --this.activeCount_;
202 this.addPoint(time, this.activeCount_);
203 }
204 };
205
206 return SourceCountDataSeries;
207 })();
208
209 /**
210 * Tracks the number of sockets currently in use. Needs special handling of
211 * SSL sockets, so can't just use a normal SourceCountDataSeries.
212 */
213 var SocketsInUseDataSeries = (function() {
214 'use strict';
215
216 var superClass = SourceCountDataSeries;
217
218 /**
219 * @constructor
220 */
221 function SocketsInUseDataSeries() {
222 superClass.call(this, EventSourceType.SOCKET, EventType.SOCKET_IN_USE);
223 }
224
225 SocketsInUseDataSeries.prototype = {
226 // Inherit the superclass's methods.
227 __proto__: superClass.prototype,
228
229 onReceivedLogEntry: function(entry) {
230 // SSL sockets have two nested SOCKET_IN_USE events. This is needed to
231 // mark SSL sockets as unused after SSL negotiation.
232 if (entry.type == EventType.SSL_CONNECT &&
233 entry.phase == EventPhase.PHASE_END) {
234 this.onEndEvent(entry.source.id, entry.time);
235 return;
236 }
237 superClass.prototype.onReceivedLogEntry.call(this, entry);
238 }
239 };
240
241 return SocketsInUseDataSeries;
242 })();
243
244 /**
245 * Tracks approximate data rate using individual data transfer events.
246 * Abstract class, doesn't implement onReceivedLogEntry.
247 */
248 var TransferRateDataSeries = (function() {
249 'use strict';
250
251 var superClass = TimelineDataSeries;
252
253 /**
254 * @constructor
255 */
256 function TransferRateDataSeries() {
257 superClass.call(this, TimelineDataType.BYTES_PER_SECOND);
258 }
259
260 TransferRateDataSeries.prototype = {
261 // Inherit the superclass's methods.
262 __proto__: superClass.prototype,
263
264 /**
265 * Returns the average data rate over each interval, only taking into
266 * account transfers that occurred within each interval.
267 * TODO(mmenke): Do something better.
268 */
269 getValuesInternal_: function(startTime, stepSize, count) {
270 // Find the first DataPoint after |startTime| - |stepSize|.
271 var nextPoint = 0;
272 while (nextPoint < this.dataPoints_.length &&
273 this.dataPoints_[nextPoint].time < startTime - stepSize) {
274 ++nextPoint;
275 }
276
277 var values = [];
278 var time = startTime;
279 for (var i = 0; i < count; ++i) {
280 // Calculate total bytes transferred from |time| - |stepSize|
281 // to |time|. We look at the transfers before |time| to give
282 // us generally non-varying values for a given time.
283 var transferred = 0;
284 while (nextPoint < this.dataPoints_.length &&
285 this.dataPoints_[nextPoint].time < time) {
286 transferred += this.dataPoints_[nextPoint].value;
287 ++nextPoint;
288 }
289 // Calculate bytes per second.
290 values[i] = 1000 * transferred / stepSize;
291 time += stepSize;
292 }
293 return values;
294 }
295 };
296
297 return TransferRateDataSeries;
298 })();
299
300 /**
301 * Tracks TCP and UDP transfer rate.
302 */
303 var NetworkTransferRateDataSeries = (function() {
304 'use strict';
305
306 var superClass = TransferRateDataSeries;
307
308 /**
309 * |tcpEvent| and |udpEvent| are the event types for data transfers using
310 * TCP and UDP, respectively.
311 * @constructor
312 */
313 function NetworkTransferRateDataSeries(tcpEvent, udpEvent) {
314 superClass.call(this);
315 this.tcpEvent_ = tcpEvent;
316 this.udpEvent_ = udpEvent;
317 }
318
319 NetworkTransferRateDataSeries.prototype = {
320 // Inherit the superclass's methods.
321 __proto__: superClass.prototype,
322
323 onReceivedLogEntry: function(entry) {
324 if (entry.type != this.tcpEvent_ && entry.type != this.udpEvent_)
325 return;
326 this.addPoint(entry.time, entry.params.byte_count);
327 },
328 };
329
330 return NetworkTransferRateDataSeries;
331 })();
332
333 /**
334 * Tracks disk cache read or write rate. Doesn't include clearing, opening,
335 * or dooming entries, as they don't have clear size values.
336 */
337 var DiskCacheTransferRateDataSeries = (function() {
338 'use strict';
339
340 var superClass = TransferRateDataSeries;
341
342 /**
343 * @constructor
344 */
345 function DiskCacheTransferRateDataSeries(eventType) {
346 superClass.call(this);
347 this.eventType_ = eventType;
348 }
349
350 DiskCacheTransferRateDataSeries.prototype = {
351 // Inherit the superclass's methods.
352 __proto__: superClass.prototype,
353
354 onReceivedLogEntry: function(entry) {
355 if (entry.source.type != EventSourceType.DISK_CACHE_ENTRY ||
356 entry.type != this.eventType_ ||
357 entry.phase != EventPhase.PHASE_END) {
358 return;
359 }
360 // The disk cache has a lot of 0-length writes, when truncating entries.
361 // Ignore those.
362 if (entry.params.bytes_copied != 0)
363 this.addPoint(entry.time, entry.params.bytes_copied);
364 }
365 };
366
367 return DiskCacheTransferRateDataSeries;
368 })();
369
OLDNEW
« no previous file with comments | « netlog_viewer/time_util.js ('k') | netlog_viewer/timeline_graph_view.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698