LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/base - ratetracker.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 74 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/base/ratetracker.h"
      12             : 
      13             : #include <stddef.h>
      14             : 
      15             : #include <algorithm>
      16             : 
      17             : #include "webrtc/base/checks.h"
      18             : #include "webrtc/base/timeutils.h"
      19             : 
      20             : namespace rtc {
      21             : 
      22             : static const int64_t kTimeUnset = -1;
      23             : 
      24           0 : RateTracker::RateTracker(int64_t bucket_milliseconds, size_t bucket_count)
      25             :     : bucket_milliseconds_(bucket_milliseconds),
      26             :       bucket_count_(bucket_count),
      27           0 :       sample_buckets_(new size_t[bucket_count + 1]),
      28             :       total_sample_count_(0u),
      29           0 :       bucket_start_time_milliseconds_(kTimeUnset) {
      30           0 :   RTC_CHECK(bucket_milliseconds > 0);
      31           0 :   RTC_CHECK(bucket_count > 0);
      32           0 : }
      33             : 
      34           0 : RateTracker::~RateTracker() {
      35           0 :   delete[] sample_buckets_;
      36           0 : }
      37             : 
      38           0 : double RateTracker::ComputeRateForInterval(
      39             :     int64_t interval_milliseconds) const {
      40           0 :   if (bucket_start_time_milliseconds_ == kTimeUnset) {
      41           0 :     return 0.0;
      42             :   }
      43           0 :   int64_t current_time = Time();
      44             :   // Calculate which buckets to sum up given the current time.  If the time
      45             :   // has passed to a new bucket then we have to skip some of the oldest buckets.
      46             :   int64_t available_interval_milliseconds =
      47             :       std::min(interval_milliseconds,
      48           0 :                bucket_milliseconds_ * static_cast<int64_t>(bucket_count_));
      49             :   // number of old buckets (i.e. after the current bucket in the ring buffer)
      50             :   // that are expired given our current time interval.
      51             :   size_t buckets_to_skip;
      52             :   // Number of milliseconds of the first bucket that are not a portion of the
      53             :   // current interval.
      54             :   int64_t milliseconds_to_skip;
      55           0 :   if (current_time >
      56           0 :       initialization_time_milliseconds_ + available_interval_milliseconds) {
      57             :     int64_t time_to_skip =
      58           0 :         current_time - bucket_start_time_milliseconds_ +
      59           0 :         static_cast<int64_t>(bucket_count_) * bucket_milliseconds_ -
      60           0 :         available_interval_milliseconds;
      61           0 :     buckets_to_skip = time_to_skip / bucket_milliseconds_;
      62           0 :     milliseconds_to_skip = time_to_skip % bucket_milliseconds_;
      63             :   } else {
      64           0 :     buckets_to_skip = bucket_count_ - current_bucket_;
      65           0 :     milliseconds_to_skip = 0;
      66             :     available_interval_milliseconds =
      67           0 :         TimeDiff(current_time, initialization_time_milliseconds_);
      68             :     // Let one bucket interval pass after initialization before reporting.
      69           0 :     if (available_interval_milliseconds < bucket_milliseconds_) {
      70           0 :       return 0.0;
      71             :     }
      72             :   }
      73             :   // If we're skipping all buckets that means that there have been no samples
      74             :   // within the sampling interval so report 0.
      75           0 :   if (buckets_to_skip > bucket_count_ || available_interval_milliseconds == 0) {
      76           0 :     return 0.0;
      77             :   }
      78           0 :   size_t start_bucket = NextBucketIndex(current_bucket_ + buckets_to_skip);
      79             :   // Only count a portion of the first bucket according to how much of the
      80             :   // first bucket is within the current interval.
      81           0 :   size_t total_samples = ((sample_buckets_[start_bucket] *
      82           0 :       (bucket_milliseconds_ - milliseconds_to_skip)) +
      83           0 :       (bucket_milliseconds_ >> 1)) /
      84           0 :       bucket_milliseconds_;
      85             :   // All other buckets in the interval are counted in their entirety.
      86           0 :   for (size_t i = NextBucketIndex(start_bucket);
      87           0 :       i != NextBucketIndex(current_bucket_);
      88             :       i = NextBucketIndex(i)) {
      89           0 :     total_samples += sample_buckets_[i];
      90             :   }
      91             :   // Convert to samples per second.
      92           0 :   return static_cast<double>(total_samples * 1000) /
      93           0 :          static_cast<double>(available_interval_milliseconds);
      94             : }
      95             : 
      96           0 : double RateTracker::ComputeTotalRate() const {
      97           0 :   if (bucket_start_time_milliseconds_ == kTimeUnset) {
      98           0 :     return 0.0;
      99             :   }
     100           0 :   int64_t current_time = Time();
     101           0 :   if (current_time <= initialization_time_milliseconds_) {
     102           0 :     return 0.0;
     103             :   }
     104           0 :   return static_cast<double>(total_sample_count_ * 1000) /
     105           0 :          static_cast<double>(
     106           0 :              TimeDiff(current_time, initialization_time_milliseconds_));
     107             : }
     108             : 
     109           0 : size_t RateTracker::TotalSampleCount() const {
     110           0 :   return total_sample_count_;
     111             : }
     112             : 
     113           0 : void RateTracker::AddSamples(size_t sample_count) {
     114           0 :   EnsureInitialized();
     115           0 :   int64_t current_time = Time();
     116             :   // Advance the current bucket as needed for the current time, and reset
     117             :   // bucket counts as we advance.
     118           0 :   for (size_t i = 0;
     119           0 :        i <= bucket_count_ &&
     120           0 :        current_time >= bucket_start_time_milliseconds_ + bucket_milliseconds_;
     121             :        ++i) {
     122           0 :     bucket_start_time_milliseconds_ += bucket_milliseconds_;
     123           0 :     current_bucket_ = NextBucketIndex(current_bucket_);
     124           0 :     sample_buckets_[current_bucket_] = 0;
     125             :   }
     126             :   // Ensure that bucket_start_time_milliseconds_ is updated appropriately if
     127             :   // the entire buffer of samples has been expired.
     128           0 :   bucket_start_time_milliseconds_ += bucket_milliseconds_ *
     129           0 :       ((current_time - bucket_start_time_milliseconds_) / bucket_milliseconds_);
     130             :   // Add all samples in the bucket that includes the current time.
     131           0 :   sample_buckets_[current_bucket_] += sample_count;
     132           0 :   total_sample_count_ += sample_count;
     133           0 : }
     134             : 
     135           0 : int64_t RateTracker::Time() const {
     136           0 :   return rtc::TimeMillis();
     137             : }
     138             : 
     139           0 : void RateTracker::EnsureInitialized() {
     140           0 :   if (bucket_start_time_milliseconds_ == kTimeUnset) {
     141           0 :     initialization_time_milliseconds_ = Time();
     142           0 :     bucket_start_time_milliseconds_ = initialization_time_milliseconds_;
     143           0 :     current_bucket_ = 0;
     144             :     // We only need to initialize the first bucket because we reset buckets when
     145             :     // current_bucket_ increments.
     146           0 :     sample_buckets_[current_bucket_] = 0;
     147             :   }
     148           0 : }
     149             : 
     150           0 : size_t RateTracker::NextBucketIndex(size_t bucket_index) const {
     151           0 :   return (bucket_index + 1u) % (bucket_count_ + 1u);
     152             : }
     153             : 
     154             : }  // namespace rtc

Generated by: LCOV version 1.13