summaryrefslogtreecommitdiffstats
path: root/remoting/protocol/performance_tracker.cc
diff options
context:
space:
mode:
authorsergeyu <sergeyu@chromium.org>2015-09-16 17:45:24 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-17 00:46:24 +0000
commitaa1f0239f0a5d0ace93c63022829fcf39fee99e7 (patch)
tree0a15e80333e1e0925ef42596526f5b066d052b66 /remoting/protocol/performance_tracker.cc
parentd24401d628410cc67c4ae7a7bc9c3a5e65fa0572 (diff)
downloadchromium_src-aa1f0239f0a5d0ace93c63022829fcf39fee99e7.zip
chromium_src-aa1f0239f0a5d0ace93c63022829fcf39fee99e7.tar.gz
chromium_src-aa1f0239f0a5d0ace93c63022829fcf39fee99e7.tar.bz2
Rename/Move ChromotingStats->protocol::PerformanceTracker
The class will be used directly from protocol dispatchers, so it needs to be accessible on the protocol layer. Also renamed it so the name reflects what the class is responsible for. Review URL: https://codereview.chromium.org/1351723004 Cr-Commit-Position: refs/heads/master@{#349295}
Diffstat (limited to 'remoting/protocol/performance_tracker.cc')
-rw-r--r--remoting/protocol/performance_tracker.cc165
1 files changed, 165 insertions, 0 deletions
diff --git a/remoting/protocol/performance_tracker.cc b/remoting/protocol/performance_tracker.cc
new file mode 100644
index 0000000..b192b56
--- /dev/null
+++ b/remoting/protocol/performance_tracker.cc
@@ -0,0 +1,165 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/protocol/performance_tracker.h"
+
+#include "remoting/proto/video.pb.h"
+
+namespace {
+
+// We take the last 10 latency numbers and report the average.
+const int kLatencySampleSize = 10;
+
+// UMA histogram names.
+const char kRoundTripLatencyHistogram[] = "Chromoting.Video.RoundTripLatency";
+const char kVideoCaptureLatencyHistogram[] = "Chromoting.Video.CaptureLatency";
+const char kVideoEncodeLatencyHistogram[] = "Chromoting.Video.EncodeLatency";
+const char kVideoDecodeLatencyHistogram[] = "Chromoting.Video.DecodeLatency";
+const char kVideoPaintLatencyHistogram[] = "Chromoting.Video.PaintLatency";
+const char kVideoFrameRateHistogram[] = "Chromoting.Video.FrameRate";
+const char kVideoPacketRateHistogram[] = "Chromoting.Video.PacketRate";
+const char kVideoBandwidthHistogram[] = "Chromoting.Video.Bandwidth";
+
+// Custom count and custom time histograms are log-scaled by default. This
+// results in fine-grained buckets at lower values and wider-ranged buckets
+// closer to the maximum.
+// The values defined for each histogram below are based on the 99th percentile
+// numbers for the corresponding metric over a recent 28-day period.
+// Values above the maximum defined for a histogram end up in the max-bucket.
+// If the minimum for a UMA histogram is set to be < 1, it is implicitly
+// normalized to 1.
+// See $/src/base/metrics/histogram.h for more details.
+
+// Video-specific metrics are stored in a custom times histogram.
+const int kVideoActionsHistogramsMinMs = 1;
+const int kVideoActionsHistogramsMaxMs = 250;
+const int kVideoActionsHistogramsBuckets = 50;
+
+// Round-trip latency values are stored in a custom times histogram.
+const int kLatencyHistogramMinMs = 1;
+const int kLatencyHistogramMaxMs = 20000;
+const int kLatencyHistogramBuckets = 50;
+
+// Bandwidth statistics are stored in a custom counts histogram.
+const int kBandwidthHistogramMinBps = 0;
+const int kBandwidthHistogramMaxBps = 10 * 1000 * 1000;
+const int kBandwidthHistogramBuckets = 100;
+
+// Frame rate is stored in a custom enum histogram, because we we want to record
+// the frequency of each discrete value, rather than using log-scaled buckets.
+// We don't expect video frame rate to be greater than 40fps. Setting a maximum
+// of 100fps will leave some room for future improvements, and account for any
+// bursts of packets. Enum histograms expect samples to be less than the
+// boundary value, so set to 101.
+const int kMaxFramesPerSec = 101;
+
+} // namespace
+
+namespace remoting {
+namespace protocol {
+
+PerformanceTracker::PerformanceTracker()
+ : video_bandwidth_(
+ base::TimeDelta::FromSeconds(kStatsUpdateFrequencyInSeconds)),
+ video_frame_rate_(
+ base::TimeDelta::FromSeconds(kStatsUpdateFrequencyInSeconds)),
+ video_packet_rate_(
+ base::TimeDelta::FromSeconds(kStatsUpdateFrequencyInSeconds)),
+ video_capture_ms_(kLatencySampleSize),
+ video_encode_ms_(kLatencySampleSize),
+ video_decode_ms_(kLatencySampleSize),
+ video_paint_ms_(kLatencySampleSize),
+ round_trip_ms_(kLatencySampleSize) {}
+
+PerformanceTracker::~PerformanceTracker() {
+}
+
+void PerformanceTracker::SetUpdateUmaCallbacks(
+ UpdateUmaCustomHistogramCallback update_uma_custom_counts_callback,
+ UpdateUmaCustomHistogramCallback update_uma_custom_times_callback,
+ UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) {
+ uma_custom_counts_updater_ = update_uma_custom_counts_callback;
+ uma_custom_times_updater_ = update_uma_custom_times_callback;
+ uma_enum_histogram_updater_ = update_uma_enum_histogram_callback;
+}
+
+void PerformanceTracker::RecordVideoPacketStats(const VideoPacket& packet) {
+ // Record this received packet, even if it is empty.
+ video_packet_rate_.Record(1);
+
+ // Record the RTT, even for empty packets, otherwise input events that
+ // do not cause an on-screen change can give very large, bogus RTTs.
+ if (packet.has_latest_event_timestamp() &&
+ packet.latest_event_timestamp() > latest_input_event_timestamp_) {
+ latest_input_event_timestamp_ = packet.latest_event_timestamp();
+
+ base::TimeDelta round_trip_latency =
+ base::Time::Now() -
+ base::Time::FromInternalValue(packet.latest_event_timestamp());
+
+ round_trip_ms_.Record(round_trip_latency.InMilliseconds());
+
+ if (!uma_custom_times_updater_.is_null())
+ uma_custom_times_updater_.Run(
+ kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(),
+ kLatencyHistogramMinMs, kLatencyHistogramMaxMs,
+ kLatencyHistogramBuckets);
+ }
+
+ // If the packet is empty, there are no other stats to update.
+ if (!packet.data().size())
+ return;
+
+ video_frame_rate_.Record(1);
+ video_bandwidth_.Record(packet.data().size());
+
+ if (packet.has_capture_time_ms()) {
+ video_capture_ms_.Record(packet.capture_time_ms());
+ if (!uma_custom_times_updater_.is_null())
+ uma_custom_times_updater_.Run(
+ kVideoCaptureLatencyHistogram, packet.capture_time_ms(),
+ kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+ kVideoActionsHistogramsBuckets);
+ }
+
+ if (packet.has_encode_time_ms()) {
+ video_encode_ms_.Record(packet.encode_time_ms());
+ if (!uma_custom_times_updater_.is_null())
+ uma_custom_times_updater_.Run(
+ kVideoEncodeLatencyHistogram, packet.encode_time_ms(),
+ kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+ kVideoActionsHistogramsBuckets);
+ }
+}
+
+void PerformanceTracker::RecordDecodeTime(double value) {
+ video_decode_ms_.Record(value);
+ if (!uma_custom_times_updater_.is_null())
+ uma_custom_times_updater_.Run(
+ kVideoDecodeLatencyHistogram, value, kVideoActionsHistogramsMinMs,
+ kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
+}
+
+void PerformanceTracker::RecordPaintTime(double value) {
+ video_paint_ms_.Record(value);
+ if (!uma_custom_times_updater_.is_null())
+ uma_custom_times_updater_.Run(
+ kVideoPaintLatencyHistogram, value, kVideoActionsHistogramsMinMs,
+ kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
+}
+
+void PerformanceTracker::UploadRateStatsToUma() {
+ if (!uma_enum_histogram_updater_.is_null()) {
+ uma_enum_histogram_updater_.Run(kVideoFrameRateHistogram,
+ video_frame_rate(), kMaxFramesPerSec);
+ uma_enum_histogram_updater_.Run(kVideoPacketRateHistogram,
+ video_packet_rate(), kMaxFramesPerSec);
+ uma_custom_counts_updater_.Run(
+ kVideoBandwidthHistogram, video_bandwidth(), kBandwidthHistogramMinBps,
+ kBandwidthHistogramMaxBps, kBandwidthHistogramBuckets);
+ }
+}
+
+} // namespace protocol
+} // namespace remoting