Temporarily make lastchange use only the git hash.
[chromium-blink-merge.git] / net / base / bandwidth_metrics.h
blobe5f2646c7dc71ad5b0a96e1f5d94eaa0ab5fb56a
1 // Copyright (c) 2011 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.
5 #ifndef NET_BASE_BANDWIDTH_METRICS_H_
6 #define NET_BASE_BANDWIDTH_METRICS_H_
8 #include <list>
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/time/time.h"
14 namespace net {
16 // Tracks statistics about the bandwidth metrics over time. In order to
17 // measure, this class needs to know when individual streams are in progress,
18 // so that it can know when to discount idle time. The BandwidthMetrics
19 // is unidirectional - it should only be used to record upload or download
20 // bandwidth, but not both.
22 // Note, the easiest thing to do is to just measure each stream and average
23 // them or add them. However, this does not work. If multiple streams are in
24 // progress concurrently, you have to look at the aggregate bandwidth at any
25 // point in time.
27 // Example:
28 // Imagine 4 streams opening and closing with overlapping time.
29 // We can't measure bandwidth by looking at any individual stream.
30 // We can only measure actual bandwidth by looking at the bandwidth
31 // across all open streams.
33 // Time --------------------------------------->
34 // s1 +----------------+
35 // s2 +----------------+
36 // s3 +--------------+
37 // s4 +--------------+
39 // Example usage:
41 // BandwidthMetrics tracker;
43 // // When a stream is created
44 // tracker.StartStream();
46 // // When data is transferred on any stream
47 // tracker.RecordSample(bytes);
49 // // When the stream is finished
50 // tracker.StopStream();
52 // NOTE: This class is not thread safe.
54 class BandwidthMetrics {
55 public:
56 BandwidthMetrics()
57 : num_streams_in_progress_(0),
58 num_data_samples_(0),
59 data_sum_(0.0),
60 bytes_since_last_start_(0) {
63 // Get the bandwidth. Returns Kbps (kilo-bits-per-second).
64 double bandwidth() const {
65 return data_sum_ / num_data_samples_;
68 // Record that we've started a stream.
69 void StartStream() {
70 // If we're the only stream, we've finished some idle time. Record a new
71 // timestamp to indicate the start of data flow.
72 if (++num_streams_in_progress_ == 1) {
73 last_start_ = base::TimeTicks::HighResNow();
74 bytes_since_last_start_ = 0;
78 // Track that we've completed a stream.
79 void StopStream() {
80 if (--num_streams_in_progress_ == 0) {
81 // We don't use small streams when tracking bandwidth because they are not
82 // precise; imagine a 25 byte stream. The sample is too small to make
83 // a good measurement.
84 // 20KB is an arbitrary value. We might want to use a lesser value.
85 static const int64 kRecordSizeThreshold = 20 * 1024;
86 if (bytes_since_last_start_ < kRecordSizeThreshold)
87 return;
89 base::TimeDelta delta = base::TimeTicks::HighResNow() - last_start_;
90 double ms = delta.InMillisecondsF();
91 if (ms > 0.0) {
92 double kbps = static_cast<double>(bytes_since_last_start_) * 8 / ms;
93 ++num_data_samples_;
94 data_sum_ += kbps;
95 VLOG(1) << "Bandwidth: " << kbps
96 << "Kbps (avg " << bandwidth() << "Kbps)";
97 int kbps_int = static_cast<int>(kbps);
98 UMA_HISTOGRAM_COUNTS_10000("Net.DownloadBandwidth", kbps_int);
103 // Add a sample of the number of bytes read from the network into the tracker.
104 void RecordBytes(int bytes) {
105 DCHECK(num_streams_in_progress_);
106 bytes_since_last_start_ += static_cast<int64>(bytes);
109 private:
110 int num_streams_in_progress_; // The number of streams in progress.
111 // TODO(mbelshe): Use a rolling buffer of 30 samples instead of an average.
112 int num_data_samples_; // The number of samples collected.
113 double data_sum_; // The sum of all samples collected.
114 int64 bytes_since_last_start_; // Bytes tracked during this "session".
115 base::TimeTicks last_start_; // Timestamp of the begin of this "session".
118 // A utility class for managing the lifecycle of a measured stream.
119 // It is important that we not leave unclosed streams, and this class helps
120 // ensure we always stop them.
121 class ScopedBandwidthMetrics {
122 public:
123 ScopedBandwidthMetrics();
124 ~ScopedBandwidthMetrics();
126 void StartStream();
127 void StopStream();
128 void RecordBytes(int bytes);
130 private:
131 bool started_;
134 } // namespace net
136 #endif // NET_BASE_BANDWIDTH_METRICS_H_