| 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 |