summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc')
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc201
1 files changed, 201 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
new file mode 100644
index 00000000000..ad0fb1866db
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
@@ -0,0 +1,201 @@
+// Copyright 2014 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 "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
+#include "third_party/blink/renderer/platform/scheduler/child/default_params.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+// Workers could be short-lived, set a shorter interval than
+// the renderer thread.
+constexpr base::TimeDelta kUnspecifiedWorkerThreadLoadTrackerReportingInterval =
+ base::TimeDelta::FromSeconds(1);
+
+void ReportWorkerTaskLoad(base::TimeTicks time, double load) {
+ int load_percentage = static_cast<int>(load * 100);
+ DCHECK_LE(load_percentage, 100);
+ // TODO(kinuko): Maybe we also want to separately log when the associated
+ // tab is in foreground and when not.
+ UMA_HISTOGRAM_PERCENTAGE("WorkerScheduler.WorkerThreadLoad", load_percentage);
+}
+
+// TODO(scheduler-dev): Remove conversions when Blink starts using
+// base::TimeTicks instead of doubles for time.
+base::TimeTicks MonotonicTimeInSecondsToTimeTicks(
+ double monotonic_time_in_seconds) {
+ return base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(monotonic_time_in_seconds);
+}
+
+} // namespace
+
+WorkerThreadScheduler::WorkerThreadScheduler(
+ WebThreadType thread_type,
+ std::unique_ptr<TaskQueueManager> task_queue_manager,
+ WorkerSchedulerProxy* proxy)
+ : NonMainThreadScheduler(
+ std::make_unique<WorkerSchedulerHelper>(std::move(task_queue_manager),
+ this)),
+ idle_helper_(helper_.get(),
+ this,
+ "WorkerSchedulerIdlePeriod",
+ base::TimeDelta::FromMilliseconds(300),
+ helper_->NewTaskQueue(TaskQueue::Spec("worker_idle_tq"))),
+ idle_canceled_delayed_task_sweeper_(helper_.get(),
+ idle_helper_.IdleTaskRunner()),
+ load_tracker_(helper_->NowTicks(),
+ base::BindRepeating(&ReportWorkerTaskLoad),
+ kUnspecifiedWorkerThreadLoadTrackerReportingInterval),
+ throttling_state_(proxy ? proxy->throttling_state()
+ : FrameScheduler::ThrottlingState::kNotThrottled),
+ worker_metrics_helper_(thread_type),
+ weak_factory_(this) {
+ thread_start_time_ = helper_->NowTicks();
+ load_tracker_.Resume(thread_start_time_);
+ helper_->AddTaskTimeObserver(this);
+
+ if (proxy) {
+ worker_metrics_helper_.SetParentFrameType(proxy->parent_frame_type());
+ proxy->OnWorkerSchedulerCreated(GetWeakPtr());
+ }
+
+ TRACE_EVENT_OBJECT_CREATED_WITH_ID(
+ TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this);
+}
+
+WorkerThreadScheduler::~WorkerThreadScheduler() {
+ TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+ TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this);
+
+ helper_->RemoveTaskTimeObserver(this);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WorkerThreadScheduler::DefaultTaskRunner() {
+ DCHECK(initialized_);
+ return helper_->DefaultWorkerTaskQueue();
+}
+
+scoped_refptr<SingleThreadIdleTaskRunner>
+WorkerThreadScheduler::IdleTaskRunner() {
+ DCHECK(initialized_);
+ return idle_helper_.IdleTaskRunner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WorkerThreadScheduler::IPCTaskRunner() {
+ return base::ThreadTaskRunnerHandle::Get();
+}
+
+bool WorkerThreadScheduler::CanExceedIdleDeadlineIfRequired() const {
+ DCHECK(initialized_);
+ return idle_helper_.CanExceedIdleDeadlineIfRequired();
+}
+
+bool WorkerThreadScheduler::ShouldYieldForHighPriorityWork() {
+ // We don't consider any work as being high priority on workers.
+ return false;
+}
+
+void WorkerThreadScheduler::AddTaskObserver(
+ base::MessageLoop::TaskObserver* task_observer) {
+ DCHECK(initialized_);
+ helper_->AddTaskObserver(task_observer);
+}
+
+void WorkerThreadScheduler::RemoveTaskObserver(
+ base::MessageLoop::TaskObserver* task_observer) {
+ DCHECK(initialized_);
+ helper_->RemoveTaskObserver(task_observer);
+}
+
+void WorkerThreadScheduler::Shutdown() {
+ DCHECK(initialized_);
+ load_tracker_.RecordIdle(helper_->NowTicks());
+ base::TimeTicks end_time = helper_->NowTicks();
+ base::TimeDelta delta = end_time - thread_start_time_;
+
+ // The lifetime could be radically different for different workers,
+ // some workers could be short-lived (but last at least 1 sec in
+ // Service Workers case) or could be around as long as the tab is open.
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "WorkerThread.Runtime", delta, base::TimeDelta::FromSeconds(1),
+ base::TimeDelta::FromDays(1), 50 /* bucket count */);
+ helper_->Shutdown();
+}
+
+scoped_refptr<WorkerTaskQueue> WorkerThreadScheduler::DefaultTaskQueue() {
+ DCHECK(initialized_);
+ return helper_->DefaultWorkerTaskQueue();
+}
+
+void WorkerThreadScheduler::Init() {
+ initialized_ = true;
+ idle_helper_.EnableLongIdlePeriod();
+}
+
+void WorkerThreadScheduler::OnTaskCompleted(
+ WorkerTaskQueue* worker_task_queue,
+ const TaskQueue::Task& task,
+ base::TimeTicks start,
+ base::TimeTicks end,
+ base::Optional<base::TimeDelta> thread_time) {
+ worker_metrics_helper_.RecordTaskMetrics(worker_task_queue, task, start, end,
+ thread_time);
+}
+
+SchedulerHelper* WorkerThreadScheduler::GetSchedulerHelperForTesting() {
+ return helper_.get();
+}
+
+bool WorkerThreadScheduler::CanEnterLongIdlePeriod(base::TimeTicks,
+ base::TimeDelta*) {
+ return true;
+}
+
+base::TimeTicks WorkerThreadScheduler::CurrentIdleTaskDeadlineForTesting()
+ const {
+ return idle_helper_.CurrentIdleTaskDeadline();
+}
+
+void WorkerThreadScheduler::WillProcessTask(double start_time) {}
+
+void WorkerThreadScheduler::DidProcessTask(double start_time, double end_time) {
+ base::TimeTicks start_time_ticks =
+ MonotonicTimeInSecondsToTimeTicks(start_time);
+ base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time);
+
+ load_tracker_.RecordTaskTime(start_time_ticks, end_time_ticks);
+}
+
+void WorkerThreadScheduler::OnThrottlingStateChanged(
+ FrameScheduler::ThrottlingState throttling_state) {
+ throttling_state_ = throttling_state;
+}
+
+scoped_refptr<WorkerTaskQueue> WorkerThreadScheduler::ControlTaskQueue() {
+ return helper_->ControlWorkerTaskQueue();
+}
+
+base::WeakPtr<WorkerThreadScheduler> WorkerThreadScheduler::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+} // namespace scheduler
+} // namespace blink