Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / remoting / protocol / performance_tracker.cc
blob271336b588dc68f3594bcdeb12b82522287ed379
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
3 // found in the LICENSE file.
5 #include "remoting/protocol/performance_tracker.h"
7 #include "remoting/proto/video.pb.h"
9 namespace {
11 // We take the last 10 latency numbers and report the average.
12 const int kLatencySampleSize = 10;
14 // UMA histogram names.
15 const char kRoundTripLatencyHistogram[] = "Chromoting.Video.RoundTripLatency";
16 const char kVideoCaptureLatencyHistogram[] = "Chromoting.Video.CaptureLatency";
17 const char kVideoEncodeLatencyHistogram[] = "Chromoting.Video.EncodeLatency";
18 const char kVideoDecodeLatencyHistogram[] = "Chromoting.Video.DecodeLatency";
19 const char kVideoPaintLatencyHistogram[] = "Chromoting.Video.PaintLatency";
20 const char kVideoFrameRateHistogram[] = "Chromoting.Video.FrameRate";
21 const char kVideoPacketRateHistogram[] = "Chromoting.Video.PacketRate";
22 const char kVideoBandwidthHistogram[] = "Chromoting.Video.Bandwidth";
24 // 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
26 // closer to the maximum.
27 // 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.
29 // 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
31 // normalized to 1.
32 // See $/src/base/metrics/histogram.h for more details.
34 // Video-specific metrics are stored in a custom times histogram.
35 const int kVideoActionsHistogramsMinMs = 1;
36 const int kVideoActionsHistogramsMaxMs = 250;
37 const int kVideoActionsHistogramsBuckets = 50;
39 // Round-trip latency values are stored in a custom times histogram.
40 const int kLatencyHistogramMinMs = 1;
41 const int kLatencyHistogramMaxMs = 20000;
42 const int kLatencyHistogramBuckets = 50;
44 // Bandwidth statistics are stored in a custom counts histogram.
45 const int kBandwidthHistogramMinBps = 0;
46 const int kBandwidthHistogramMaxBps = 10 * 1000 * 1000;
47 const int kBandwidthHistogramBuckets = 100;
49 // 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.
51 // 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
53 // bursts of packets. Enum histograms expect samples to be less than the
54 // boundary value, so set to 101.
55 const int kMaxFramesPerSec = 101;
57 } // namespace
59 namespace remoting {
60 namespace protocol {
62 PerformanceTracker::PerformanceTracker()
63 : video_bandwidth_(base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)),
64 video_frame_rate_(
65 base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)),
66 video_packet_rate_(
67 base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds)),
68 video_capture_ms_(kLatencySampleSize),
69 video_encode_ms_(kLatencySampleSize),
70 video_decode_ms_(kLatencySampleSize),
71 video_paint_ms_(kLatencySampleSize),
72 round_trip_ms_(kLatencySampleSize) {}
74 PerformanceTracker::~PerformanceTracker() {}
76 void PerformanceTracker::SetUpdateUmaCallbacks(
77 UpdateUmaCustomHistogramCallback update_uma_custom_counts_callback,
78 UpdateUmaCustomHistogramCallback update_uma_custom_times_callback,
79 UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) {
80 uma_custom_counts_updater_ = update_uma_custom_counts_callback;
81 uma_custom_times_updater_ = update_uma_custom_times_callback;
82 uma_enum_histogram_updater_ = update_uma_enum_histogram_callback;
85 void PerformanceTracker::RecordVideoPacketStats(const VideoPacket& packet) {
86 if (!is_paused_ && !upload_uma_stats_timer_.IsRunning()) {
87 upload_uma_stats_timer_.Start(
88 FROM_HERE, base::TimeDelta::FromSeconds(kStatsUpdatePeriodSeconds),
89 base::Bind(&PerformanceTracker::UploadRateStatsToUma,
90 base::Unretained(this)));
93 // Record this received packet, even if it is empty.
94 video_packet_rate_.Record(1);
96 // 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.
98 if (packet.has_latest_event_timestamp() &&
99 packet.latest_event_timestamp() > latest_input_event_timestamp_) {
100 latest_input_event_timestamp_ = packet.latest_event_timestamp();
102 base::TimeDelta round_trip_latency =
103 base::Time::Now() -
104 base::Time::FromInternalValue(packet.latest_event_timestamp());
106 round_trip_ms_.Record(round_trip_latency.InMilliseconds());
108 if (!uma_custom_times_updater_.is_null())
109 uma_custom_times_updater_.Run(
110 kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(),
111 kLatencyHistogramMinMs, kLatencyHistogramMaxMs,
112 kLatencyHistogramBuckets);
115 // If the packet is empty, there are no other stats to update.
116 if (!packet.data().size())
117 return;
119 video_frame_rate_.Record(1);
120 video_bandwidth_.Record(packet.data().size());
122 if (packet.has_capture_time_ms()) {
123 video_capture_ms_.Record(packet.capture_time_ms());
124 if (!uma_custom_times_updater_.is_null())
125 uma_custom_times_updater_.Run(
126 kVideoCaptureLatencyHistogram, packet.capture_time_ms(),
127 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
128 kVideoActionsHistogramsBuckets);
131 if (packet.has_encode_time_ms()) {
132 video_encode_ms_.Record(packet.encode_time_ms());
133 if (!uma_custom_times_updater_.is_null())
134 uma_custom_times_updater_.Run(
135 kVideoEncodeLatencyHistogram, packet.encode_time_ms(),
136 kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
137 kVideoActionsHistogramsBuckets);
141 void PerformanceTracker::RecordDecodeTime(double value) {
142 video_decode_ms_.Record(value);
143 if (!uma_custom_times_updater_.is_null())
144 uma_custom_times_updater_.Run(
145 kVideoDecodeLatencyHistogram, value, kVideoActionsHistogramsMinMs,
146 kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
149 void PerformanceTracker::RecordPaintTime(double value) {
150 video_paint_ms_.Record(value);
151 if (!uma_custom_times_updater_.is_null())
152 uma_custom_times_updater_.Run(
153 kVideoPaintLatencyHistogram, value, kVideoActionsHistogramsMinMs,
154 kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
157 void PerformanceTracker::UploadRateStatsToUma() {
158 if (!uma_enum_histogram_updater_.is_null()) {
159 uma_enum_histogram_updater_.Run(kVideoFrameRateHistogram,
160 video_frame_rate(), kMaxFramesPerSec);
161 uma_enum_histogram_updater_.Run(kVideoPacketRateHistogram,
162 video_packet_rate(), kMaxFramesPerSec);
163 uma_custom_counts_updater_.Run(
164 kVideoBandwidthHistogram, video_bandwidth(), kBandwidthHistogramMinBps,
165 kBandwidthHistogramMaxBps, kBandwidthHistogramBuckets);
169 void PerformanceTracker::OnPauseStateChanged(bool paused) {
170 is_paused_ = paused;
171 if (is_paused_) {
172 // Pause the UMA timer when the video is paused. It will be unpaused in
173 // RecordVideoPacketStats() when a new frame is received.
174 upload_uma_stats_timer_.Stop();
178 } // namespace protocol
179 } // namespace remoting