blob: af85a75c7a6be0e3499b0bd9e9784d1da3dca230 [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/chromeos/power/ml/recent_events_counter.h"
#include "base/logging.h"
namespace chromeos {
namespace power {
namespace ml {
RecentEventsCounter::RecentEventsCounter(base::TimeDelta duration,
int num_buckets)
: duration_(duration), num_buckets_(num_buckets) {
DCHECK_GT(num_buckets_, 0);
bucket_duration_ = duration_ / num_buckets_;
event_count_.resize(num_buckets_, 0);
}
RecentEventsCounter::~RecentEventsCounter() = default;
void RecentEventsCounter::Log(base::TimeDelta timestamp) {
if (timestamp < first_bucket_time_) {
// This event is too old to log.
return;
}
if (timestamp > latest_) {
latest_ = timestamp;
}
int bucket_index = GetBucketIndex(timestamp);
if (timestamp < first_bucket_time_ + duration_) {
// The event is within the current time window so increment the bucket.
event_count_[bucket_index]++;
return;
}
// The event is later than the current window for the existing data.
event_count_[bucket_index] = 1;
for (int i = first_bucket_index_; i != bucket_index;
i = (i + 1) % num_buckets_) {
event_count_[i] = 0;
}
first_bucket_index_ = (bucket_index + 1) % num_buckets_;
int num_cycles = floor(timestamp / duration_);
base::TimeDelta cycle_start = num_cycles * duration_;
int extra_buckets = floor((timestamp - cycle_start) / bucket_duration_);
first_bucket_time_ = cycle_start + extra_buckets * bucket_duration_ +
bucket_duration_ - duration_;
}
int RecentEventsCounter::GetTotal(base::TimeDelta now) {
DCHECK_GE(now, latest_);
if (now >= first_bucket_time_ + 2 * duration_) {
return 0;
}
int total = 0;
base::TimeDelta start =
std::max(first_bucket_time_, now - duration_ + bucket_duration_);
base::TimeDelta end =
std::min(now + bucket_duration_, first_bucket_time_ + duration_);
int end_index = GetBucketIndex(end);
for (int i = GetBucketIndex(start); i != end_index;
i = (i + 1) % num_buckets_) {
total += event_count_[i];
}
return total;
}
int RecentEventsCounter::GetBucketIndex(base::TimeDelta timestamp) const {
DCHECK_GE(timestamp, base::TimeDelta());
int num_cycles = floor(timestamp / duration_);
base::TimeDelta cycle_start = num_cycles * duration_;
int index = floor((timestamp - cycle_start) / bucket_duration_);
if (index >= num_buckets_) {
return num_buckets_ - 1;
}
DCHECK_GE(index, 0);
return index;
}
} // namespace ml
} // namespace power
} // namespace chromeos