OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/performance_tracker.h" | 5 #include "remoting/protocol/performance_tracker.h" |
6 | 6 |
7 #include "remoting/proto/video.pb.h" | 7 #include "remoting/proto/video.pb.h" |
8 | 8 |
9 namespace { | 9 namespace { |
10 | 10 |
11 // We take the last 10 latency numbers and report the average. | 11 // We take the last 10 latency numbers and report the average. |
12 const int kLatencySampleSize = 10; | 12 const int kLatencySampleSize = 10; |
13 | 13 |
14 // UMA histogram names. | 14 // UMA histogram names. |
15 const char kRoundTripLatencyHistogram[] = "Chromoting.Video.RoundTripLatency"; | 15 const char kRoundTripLatencyHistogram[] = "Chromoting.Video.RoundTripLatency"; |
16 const char kVideoCaptureLatencyHistogram[] = "Chromoting.Video.CaptureLatency"; | 16 const char kVideoCaptureLatencyHistogram[] = "Chromoting.Video.CaptureLatency"; |
17 const char kVideoEncodeLatencyHistogram[] = "Chromoting.Video.EncodeLatency"; | 17 const char kVideoEncodeLatencyHistogram[] = "Chromoting.Video.EncodeLatency"; |
18 const char kVideoDecodeLatencyHistogram[] = "Chromoting.Video.DecodeLatency"; | 18 const char kVideoDecodeLatencyHistogram[] = "Chromoting.Video.DecodeLatency"; |
19 const char kVideoPaintLatencyHistogram[] = "Chromoting.Video.PaintLatency"; | 19 const char kVideoPaintLatencyHistogram[] = "Chromoting.Video.PaintLatency"; |
20 const char kVideoFrameRateHistogram[] = "Chromoting.Video.FrameRate"; | 20 const char kVideoFrameRateHistogram[] = "Chromoting.Video.FrameRate"; |
21 const char kVideoPacketRateHistogram[] = "Chromoting.Video.PacketRate"; | 21 const char kVideoPacketRateHistogram[] = "Chromoting.Video.PacketRate"; |
22 const char kVideoBandwidthHistogram[] = "Chromoting.Video.Bandwidth"; | 22 const char kVideoBandwidthHistogram[] = "Chromoting.Video.Bandwidth"; |
| 23 const char kCapturePendingLatencyHistogram[] = |
| 24 "Chromoting.Video.CapturePendingLatency"; |
| 25 const char kCaptureOverheadHistogram[] = "Chromoting.Video.CaptureOverhead"; |
| 26 const char kEncodePendingLatencyHistogram[] = |
| 27 "Chromoting.Video.EncodePendingLatency"; |
| 28 const char kSendPendingLatencyHistogram[] = |
| 29 "Chromoting.Video.SendPendingLatency"; |
23 | 30 |
24 // Custom count and custom time histograms are log-scaled by default. This | 31 // Custom count and custom time histograms are log-scaled by default. This |
25 // results in fine-grained buckets at lower values and wider-ranged buckets | 32 // results in fine-grained buckets at lower values and wider-ranged buckets |
26 // closer to the maximum. | 33 // closer to the maximum. |
27 // The values defined for each histogram below are based on the 99th percentile | 34 // The values defined for each histogram below are based on the 99th percentile |
28 // numbers for the corresponding metric over a recent 28-day period. | 35 // numbers for the corresponding metric over a recent 28-day period. |
29 // Values above the maximum defined for a histogram end up in the max-bucket. | 36 // Values above the maximum defined for a histogram end up in the max-bucket. |
30 // If the minimum for a UMA histogram is set to be < 1, it is implicitly | 37 // If the minimum for a UMA histogram is set to be < 1, it is implicitly |
31 // normalized to 1. | 38 // normalized to 1. |
32 // See $/src/base/metrics/histogram.h for more details. | 39 // See $/src/base/metrics/histogram.h for more details. |
(...skipping 14 matching lines...) Expand all Loading... |
47 const int kBandwidthHistogramBuckets = 100; | 54 const int kBandwidthHistogramBuckets = 100; |
48 | 55 |
49 // Frame rate is stored in a custom enum histogram, because we we want to record | 56 // Frame rate is stored in a custom enum histogram, because we we want to record |
50 // the frequency of each discrete value, rather than using log-scaled buckets. | 57 // the frequency of each discrete value, rather than using log-scaled buckets. |
51 // We don't expect video frame rate to be greater than 40fps. Setting a maximum | 58 // We don't expect video frame rate to be greater than 40fps. Setting a maximum |
52 // of 100fps will leave some room for future improvements, and account for any | 59 // of 100fps will leave some room for future improvements, and account for any |
53 // bursts of packets. Enum histograms expect samples to be less than the | 60 // bursts of packets. Enum histograms expect samples to be less than the |
54 // boundary value, so set to 101. | 61 // boundary value, so set to 101. |
55 const int kMaxFramesPerSec = 101; | 62 const int kMaxFramesPerSec = 101; |
56 | 63 |
| 64 |
| 65 void UpdateUmaEnumHistogramStub(const std::string& histogram_name, |
| 66 int64_t value, |
| 67 int histogram_max) {} |
| 68 |
| 69 void UpdateUmaCustomHistogramStub(const std::string& histogram_name, |
| 70 int64_t value, |
| 71 int histogram_min, |
| 72 int histogram_max, |
| 73 int histogram_buckets) {} |
57 } // namespace | 74 } // namespace |
58 | 75 |
59 namespace remoting { | 76 namespace remoting { |
60 namespace protocol { | 77 namespace protocol { |
61 | 78 |
62 PerformanceTracker::PerformanceTracker() | 79 PerformanceTracker::PerformanceTracker() |
63 : video_bandwidth_(base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)), | 80 : video_bandwidth_(base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)), |
64 video_frame_rate_( | 81 video_frame_rate_( |
65 base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)), | 82 base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)), |
66 video_packet_rate_( | 83 video_packet_rate_( |
67 base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)), | 84 base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)), |
68 video_capture_ms_(kLatencySampleSize), | 85 video_capture_ms_(kLatencySampleSize), |
69 video_encode_ms_(kLatencySampleSize), | 86 video_encode_ms_(kLatencySampleSize), |
70 video_decode_ms_(kLatencySampleSize), | 87 video_decode_ms_(kLatencySampleSize), |
71 video_paint_ms_(kLatencySampleSize), | 88 video_paint_ms_(kLatencySampleSize), |
72 round_trip_ms_(kLatencySampleSize) {} | 89 round_trip_ms_(kLatencySampleSize) { |
| 90 uma_custom_counts_updater_ = base::Bind(&UpdateUmaCustomHistogramStub); |
| 91 uma_custom_times_updater_ = base::Bind(&UpdateUmaCustomHistogramStub); |
| 92 uma_enum_histogram_updater_ = base::Bind(&UpdateUmaEnumHistogramStub); |
| 93 } |
73 | 94 |
74 PerformanceTracker::~PerformanceTracker() {} | 95 PerformanceTracker::~PerformanceTracker() {} |
75 | 96 |
76 void PerformanceTracker::SetUpdateUmaCallbacks( | 97 void PerformanceTracker::SetUpdateUmaCallbacks( |
77 UpdateUmaCustomHistogramCallback update_uma_custom_counts_callback, | 98 UpdateUmaCustomHistogramCallback update_uma_custom_counts_callback, |
78 UpdateUmaCustomHistogramCallback update_uma_custom_times_callback, | 99 UpdateUmaCustomHistogramCallback update_uma_custom_times_callback, |
79 UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) { | 100 UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) { |
| 101 DCHECK(!update_uma_custom_counts_callback.is_null()); |
| 102 DCHECK(!update_uma_custom_times_callback.is_null()); |
| 103 DCHECK(!update_uma_enum_histogram_callback.is_null()); |
| 104 |
80 uma_custom_counts_updater_ = update_uma_custom_counts_callback; | 105 uma_custom_counts_updater_ = update_uma_custom_counts_callback; |
81 uma_custom_times_updater_ = update_uma_custom_times_callback; | 106 uma_custom_times_updater_ = update_uma_custom_times_callback; |
82 uma_enum_histogram_updater_ = update_uma_enum_histogram_callback; | 107 uma_enum_histogram_updater_ = update_uma_enum_histogram_callback; |
83 } | 108 } |
84 | 109 |
85 void PerformanceTracker::RecordVideoPacketStats(const VideoPacket& packet) { | 110 void PerformanceTracker::RecordVideoPacketStats(const VideoPacket& packet) { |
86 if (!is_paused_ && !upload_uma_stats_timer_.IsRunning()) { | 111 if (!is_paused_ && !upload_uma_stats_timer_.IsRunning()) { |
87 upload_uma_stats_timer_.Start( | 112 upload_uma_stats_timer_.Start( |
88 FROM_HERE, base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds), | 113 FROM_HERE, base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds), |
89 base::Bind(&PerformanceTracker::UploadRateStatsToUma, | 114 base::Bind(&PerformanceTracker::UploadRateStatsToUma, |
90 base::Unretained(this))); | 115 base::Unretained(this))); |
91 } | 116 } |
92 | 117 |
93 // Record this received packet, even if it is empty. | 118 // Record this received packet, even if it is empty. |
94 video_packet_rate_.Record(1); | 119 video_packet_rate_.Record(1); |
95 | 120 |
96 // Record the RTT, even for empty packets, otherwise input events that | 121 // Record the RTT, even for empty packets, otherwise input events that |
97 // do not cause an on-screen change can give very large, bogus RTTs. | 122 // do not cause an on-screen change can give very large, bogus RTTs. |
98 if (packet.has_latest_event_timestamp() && | 123 if (packet.has_latest_event_timestamp() && |
99 packet.latest_event_timestamp() > latest_input_event_timestamp_) { | 124 packet.latest_event_timestamp() > latest_input_event_timestamp_) { |
100 latest_input_event_timestamp_ = packet.latest_event_timestamp(); | 125 latest_input_event_timestamp_ = packet.latest_event_timestamp(); |
101 | 126 |
102 base::TimeDelta round_trip_latency = | 127 base::TimeDelta round_trip_latency = |
103 base::Time::Now() - | 128 base::Time::Now() - |
104 base::Time::FromInternalValue(packet.latest_event_timestamp()); | 129 base::Time::FromInternalValue(packet.latest_event_timestamp()); |
105 | 130 |
106 round_trip_ms_.Record(round_trip_latency.InMilliseconds()); | 131 round_trip_ms_.Record(round_trip_latency.InMilliseconds()); |
107 | 132 |
108 if (!uma_custom_times_updater_.is_null()) | 133 uma_custom_times_updater_.Run( |
109 uma_custom_times_updater_.Run( | 134 kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(), |
110 kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(), | 135 kLatencyHistogramMinMs, kLatencyHistogramMaxMs, |
111 kLatencyHistogramMinMs, kLatencyHistogramMaxMs, | 136 kLatencyHistogramBuckets); |
112 kLatencyHistogramBuckets); | |
113 } | 137 } |
114 | 138 |
115 // If the packet is empty, there are no other stats to update. | 139 // If the packet is empty, there are no other stats to update. |
116 if (!packet.data().size()) | 140 if (!packet.data().size()) |
117 return; | 141 return; |
118 | 142 |
119 video_frame_rate_.Record(1); | 143 video_frame_rate_.Record(1); |
120 video_bandwidth_.Record(packet.data().size()); | 144 video_bandwidth_.Record(packet.data().size()); |
121 | 145 |
122 if (packet.has_capture_time_ms()) { | 146 if (packet.has_capture_time_ms()) { |
123 video_capture_ms_.Record(packet.capture_time_ms()); | 147 video_capture_ms_.Record(packet.capture_time_ms()); |
124 if (!uma_custom_times_updater_.is_null()) | 148 uma_custom_times_updater_.Run( |
125 uma_custom_times_updater_.Run( | 149 kVideoCaptureLatencyHistogram, packet.capture_time_ms(), |
126 kVideoCaptureLatencyHistogram, packet.capture_time_ms(), | 150 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
127 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 151 kVideoActionsHistogramsBuckets); |
128 kVideoActionsHistogramsBuckets); | |
129 } | 152 } |
130 | 153 |
131 if (packet.has_encode_time_ms()) { | 154 if (packet.has_encode_time_ms()) { |
132 video_encode_ms_.Record(packet.encode_time_ms()); | 155 video_encode_ms_.Record(packet.encode_time_ms()); |
133 if (!uma_custom_times_updater_.is_null()) | 156 uma_custom_times_updater_.Run( |
134 uma_custom_times_updater_.Run( | 157 kVideoEncodeLatencyHistogram, packet.encode_time_ms(), |
135 kVideoEncodeLatencyHistogram, packet.encode_time_ms(), | 158 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
136 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, | 159 kVideoActionsHistogramsBuckets); |
137 kVideoActionsHistogramsBuckets); | 160 } |
| 161 |
| 162 if (packet.has_capture_pending_time_ms()) { |
| 163 uma_custom_times_updater_.Run( |
| 164 kCapturePendingLatencyHistogram, packet.capture_pending_time_ms(), |
| 165 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 166 kVideoActionsHistogramsBuckets); |
| 167 } |
| 168 |
| 169 if (packet.has_capture_overhead_time_ms()) { |
| 170 uma_custom_times_updater_.Run( |
| 171 kCaptureOverheadHistogram, packet.capture_overhead_time_ms(), |
| 172 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 173 kVideoActionsHistogramsBuckets); |
| 174 } |
| 175 |
| 176 if (packet.has_encode_pending_time_ms()) { |
| 177 uma_custom_times_updater_.Run( |
| 178 kEncodePendingLatencyHistogram, packet.encode_pending_time_ms(), |
| 179 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 180 kVideoActionsHistogramsBuckets); |
| 181 } |
| 182 |
| 183 if (packet.has_send_pending_time_ms()) { |
| 184 uma_custom_times_updater_.Run( |
| 185 kSendPendingLatencyHistogram, packet.send_pending_time_ms(), |
| 186 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs, |
| 187 kVideoActionsHistogramsBuckets); |
138 } | 188 } |
139 } | 189 } |
140 | 190 |
141 void PerformanceTracker::RecordDecodeTime(double value) { | 191 void PerformanceTracker::RecordDecodeTime(double value) { |
142 video_decode_ms_.Record(value); | 192 video_decode_ms_.Record(value); |
143 if (!uma_custom_times_updater_.is_null()) | 193 uma_custom_times_updater_.Run( |
144 uma_custom_times_updater_.Run( | 194 kVideoDecodeLatencyHistogram, value, kVideoActionsHistogramsMinMs, |
145 kVideoDecodeLatencyHistogram, value, kVideoActionsHistogramsMinMs, | 195 kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets); |
146 kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets); | |
147 } | 196 } |
148 | 197 |
149 void PerformanceTracker::RecordPaintTime(double value) { | 198 void PerformanceTracker::RecordPaintTime(double value) { |
150 video_paint_ms_.Record(value); | 199 video_paint_ms_.Record(value); |
151 if (!uma_custom_times_updater_.is_null()) | 200 uma_custom_times_updater_.Run( |
152 uma_custom_times_updater_.Run( | 201 kVideoPaintLatencyHistogram, value, kVideoActionsHistogramsMinMs, |
153 kVideoPaintLatencyHistogram, value, kVideoActionsHistogramsMinMs, | 202 kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets); |
154 kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets); | |
155 } | 203 } |
156 | 204 |
157 void PerformanceTracker::UploadRateStatsToUma() { | 205 void PerformanceTracker::UploadRateStatsToUma() { |
158 if (!uma_enum_histogram_updater_.is_null()) { | 206 uma_enum_histogram_updater_.Run(kVideoFrameRateHistogram, video_frame_rate(), |
159 uma_enum_histogram_updater_.Run(kVideoFrameRateHistogram, | 207 kMaxFramesPerSec); |
160 video_frame_rate(), kMaxFramesPerSec); | 208 uma_enum_histogram_updater_.Run(kVideoPacketRateHistogram, |
161 uma_enum_histogram_updater_.Run(kVideoPacketRateHistogram, | 209 video_packet_rate(), kMaxFramesPerSec); |
162 video_packet_rate(), kMaxFramesPerSec); | 210 uma_custom_counts_updater_.Run( |
163 uma_custom_counts_updater_.Run( | 211 kVideoBandwidthHistogram, video_bandwidth(), kBandwidthHistogramMinBps, |
164 kVideoBandwidthHistogram, video_bandwidth(), kBandwidthHistogramMinBps, | 212 kBandwidthHistogramMaxBps, kBandwidthHistogramBuckets); |
165 kBandwidthHistogramMaxBps, kBandwidthHistogramBuckets); | |
166 } | |
167 } | 213 } |
168 | 214 |
169 void PerformanceTracker::OnPauseStateChanged(bool paused) { | 215 void PerformanceTracker::OnPauseStateChanged(bool paused) { |
170 is_paused_ = paused; | 216 is_paused_ = paused; |
171 if (is_paused_) { | 217 if (is_paused_) { |
172 // Pause the UMA timer when the video is paused. It will be unpaused in | 218 // Pause the UMA timer when the video is paused. It will be unpaused in |
173 // RecordVideoPacketStats() when a new frame is received. | 219 // RecordVideoPacketStats() when a new frame is received. |
174 upload_uma_stats_timer_.Stop(); | 220 upload_uma_stats_timer_.Stop(); |
175 } | 221 } |
176 } | 222 } |
177 | 223 |
178 } // namespace protocol | 224 } // namespace protocol |
179 } // namespace remoting | 225 } // namespace remoting |
OLD | NEW |