| Index: components/scheduler/renderer/queueing_time_estimator.cc
|
| diff --git a/components/scheduler/renderer/queueing_time_estimator.cc b/components/scheduler/renderer/queueing_time_estimator.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f6fb0a57cb26e7a650667737330454f98a8b3e6d
|
| --- /dev/null
|
| +++ b/components/scheduler/renderer/queueing_time_estimator.cc
|
| @@ -0,0 +1,99 @@
|
| +// Copyright 2016 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 "components/scheduler/renderer/queueing_time_estimator.h"
|
| +
|
| +#include "base/time/default_tick_clock.h"
|
| +
|
| +namespace scheduler {
|
| +
|
| +namespace {
|
| +
|
| +base::TimeDelta ExpectedQueueingTimeFromTask(base::TimeTicks task_start,
|
| + base::TimeTicks task_end,
|
| + base::TimeTicks window_start,
|
| + base::TimeTicks window_end) {
|
| + DCHECK(task_start <= task_end);
|
| + DCHECK(task_start <= window_end);
|
| + DCHECK(window_start < window_end);
|
| + DCHECK(task_end >= window_start);
|
| + base::TimeTicks task_in_window_start_time =
|
| + std::max(task_start, window_start);
|
| + base::TimeTicks task_in_window_end_time =
|
| + std::min(task_end, window_end);
|
| + DCHECK(task_in_window_end_time <= task_in_window_end_time);
|
| +
|
| + double probability_of_this_task =
|
| + static_cast<double>((task_in_window_end_time - task_in_window_start_time)
|
| + .InMicroseconds()) /
|
| + (window_end - window_start).InMicroseconds();
|
| +
|
| + base::TimeDelta expected_queueing_duration_within_task =
|
| + ((task_end - task_in_window_start_time) +
|
| + (task_end - task_in_window_end_time)) /
|
| + 2;
|
| +
|
| + return base::TimeDelta::FromMillisecondsD(
|
| + probability_of_this_task *
|
| + expected_queueing_duration_within_task.InMillisecondsF());
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +QueueingTimeEstimator::QueueingTimeEstimator(
|
| + QueueingTimeEstimator::Client* client,
|
| + base::TickClock* time_source,
|
| + base::TimeDelta window_duration)
|
| + : client_(client),
|
| + time_source_(time_source),
|
| + outstanding_task_count_(0),
|
| + window_duration_(window_duration),
|
| + window_start_time_(time_source->NowTicks()) {}
|
| +
|
| +QueueingTimeEstimator::~QueueingTimeEstimator() {}
|
| +
|
| +void QueueingTimeEstimator::WillProcessTask(
|
| + const base::PendingTask& pending_task) {
|
| + // Avoid measuring the duration in nested run loops.
|
| + if (++outstanding_task_count_ != 1)
|
| + return;
|
| +
|
| + task_start_time_ = time_source_->NowTicks();
|
| +}
|
| +
|
| +void QueueingTimeEstimator::DidProcessTask(
|
| + const base::PendingTask& pending_task) {
|
| + if (--outstanding_task_count_ != 0)
|
| + return;
|
| +
|
| + base::TimeTicks task_end_time = time_source_->NowTicks();
|
| +
|
| + bool start_past_window =
|
| + task_start_time_ > window_start_time_ + window_duration_;
|
| + bool end_past_window =
|
| + task_end_time > window_start_time_ + window_duration_;
|
| +
|
| + while (end_past_window) {
|
| + if (!start_past_window) {
|
| + // Include the current task in this window.
|
| + current_expected_queueing_time_ += ExpectedQueueingTimeFromTask(
|
| + task_start_time_, task_end_time, window_start_time_,
|
| + window_start_time_ + window_duration_);
|
| + }
|
| + client_->OnQueueingTimeForWindowEstimated(current_expected_queueing_time_);
|
| + window_start_time_ += window_duration_;
|
| + current_expected_queueing_time_ = base::TimeDelta();
|
| +
|
| + start_past_window =
|
| + task_start_time_ > window_start_time_ + window_duration_;
|
| + end_past_window =
|
| + task_end_time > window_start_time_ + window_duration_;
|
| + }
|
| +
|
| + current_expected_queueing_time_ += ExpectedQueueingTimeFromTask(
|
| + task_start_time_, task_end_time, window_start_time_,
|
| + window_start_time_ + window_duration_);
|
| +}
|
| +
|
| +} // namespace scheduler
|
|
|