Index: third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker.cc |
diff --git a/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker.cc b/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9e5aaaf57823abc912eb9e0f171e9dfb0974a255 |
--- /dev/null |
+++ b/third_party/WebKit/Source/platform/scheduler/base/thread_load_tracker.cc |
@@ -0,0 +1,108 @@ |
+// 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 "platform/scheduler/base/thread_load_tracker.h" |
+ |
+#include <algorithm> |
+ |
+namespace blink { |
+namespace scheduler { |
+ |
+namespace { |
+ |
+const int kLoadReportingIntervalInSeconds = 1; |
+const int kWaitingPeriodBeforeReportingInSeconds = 10; |
+ |
+} // namespace |
+ |
+ThreadLoadTracker::ThreadLoadTracker(base::TimeTicks now, |
+ const Callback& callback) |
+ : time_(now), |
+ next_reporting_time_(now), |
+ thread_state_(ThreadState::ACTIVE), |
+ last_state_change_time_(now), |
+ waiting_period_( |
+ base::TimeDelta::FromSeconds(kWaitingPeriodBeforeReportingInSeconds)), |
+ reporting_interval_( |
+ base::TimeDelta::FromSeconds(kLoadReportingIntervalInSeconds)), |
+ callback_(callback) {} |
+ |
+ThreadLoadTracker::~ThreadLoadTracker() {} |
+ |
+void ThreadLoadTracker::Pause(base::TimeTicks now) { |
+ Advance(now, TaskState::IDLE); |
+ thread_state_ = ThreadState::PAUSED; |
+ last_state_change_time_ = now; |
+} |
+ |
+void ThreadLoadTracker::Resume(base::TimeTicks now) { |
+ Advance(now, TaskState::IDLE); |
+ thread_state_ = ThreadState::ACTIVE; |
+ last_state_change_time_ = now; |
+} |
+ |
+void ThreadLoadTracker::RecordTaskTime(base::TimeTicks start_time, |
+ base::TimeTicks end_time) { |
+ start_time = std::max(last_state_change_time_, start_time); |
+ end_time = std::max(last_state_change_time_, end_time); |
+ |
+ Advance(start_time, TaskState::IDLE); |
+ Advance(end_time, TaskState::TASK_RUNNING); |
+} |
+ |
+void ThreadLoadTracker::RecordIdle(base::TimeTicks now) { |
+ Advance(now, TaskState::IDLE); |
+} |
+ |
+void ThreadLoadTracker::Advance(base::TimeTicks now, TaskState task_state) { |
+ // This function advances |time_| to now and calls |callback_| |
+ // when appropriate. |
+ if (time_ > now) { |
+ return; |
+ } |
+ |
+ if (thread_state_ == ThreadState::PAUSED) { |
+ // If the load tracker is paused, bail out early. |
+ time_ = now; |
+ next_reporting_time_ = now + reporting_interval_; |
+ return; |
+ } |
+ |
+ while (time_ < now) { |
+ // Forward time_ to the earliest of following: |
+ // a) time to call |callback_| |
+ // b) requested time to forward (|now|). |
+ base::TimeTicks next_current_time = std::min(next_reporting_time_, now); |
+ |
+ base::TimeDelta delta = next_current_time - time_; |
+ |
+ // Forward time and recalculate |total_time_| and |total_runtime_|. |
+ if (thread_state_ == ThreadState::ACTIVE) { |
+ total_time_ += delta; |
+ if (task_state == TaskState::TASK_RUNNING) { |
+ total_runtime_ += delta; |
+ } |
+ } |
+ time_ = next_current_time; |
+ |
+ if (time_ == next_reporting_time_) { |
+ // Call |callback_| if need and update next callback time. |
+ if (thread_state_ == ThreadState::ACTIVE && |
+ total_time_ >= waiting_period_) { |
+ callback_.Run(time_, Load()); |
+ } |
+ next_reporting_time_ += reporting_interval_; |
+ } |
+ } |
+} |
+ |
+double ThreadLoadTracker::Load() { |
+ if (total_time_.is_zero()) { |
+ return 0; |
+ } |
+ return total_runtime_.InSecondsF() / total_time_.InSecondsF(); |
+} |
+ |
+} // namespace scheduler |
+} // namespace blink |