OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "platform/scheduler/child/worker_scheduler_impl.h" | 5 #include "platform/scheduler/child/worker_scheduler_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "base/trace_event/trace_event_argument.h" | 10 #include "base/trace_event/trace_event_argument.h" |
11 #include "platform/Histogram.h" | |
12 #include "platform/scheduler/base/time_converter.h" | 11 #include "platform/scheduler/base/time_converter.h" |
13 #include "platform/scheduler/child/scheduler_tqm_delegate.h" | 12 #include "platform/scheduler/child/scheduler_tqm_delegate.h" |
14 #include "platform/wtf/PtrUtil.h" | |
15 #include "public/platform/scheduler/base/task_queue.h" | 13 #include "public/platform/scheduler/base/task_queue.h" |
16 | 14 |
17 namespace blink { | 15 namespace blink { |
18 namespace scheduler { | 16 namespace scheduler { |
19 | 17 |
20 namespace { | 18 namespace { |
21 // Workers could be short-lived, set a shorter interval than | 19 // Workers could be short-lived, set a shorter interval than |
22 // the renderer thread. | 20 // the renderer thread. |
23 constexpr base::TimeDelta kWorkerThreadLoadTrackerReportingInterval = | 21 constexpr base::TimeDelta kWorkerThreadLoadTrackerReportingInterval = |
24 base::TimeDelta::FromSeconds(1); | 22 base::TimeDelta::FromSeconds(1); |
25 // Start reporting the load right away. | 23 // Start reporting the load right away. |
26 constexpr base::TimeDelta kWorkerThreadLoadTrackerWaitingPeriodBeforeReporting = | 24 constexpr base::TimeDelta kWorkerThreadLoadTrackerWaitingPeriodBeforeReporting = |
27 base::TimeDelta::FromSeconds(0); | 25 base::TimeDelta::FromSeconds(0); |
28 | 26 |
29 void ReportWorkerTaskLoad(base::TimeTicks time, double load) { | 27 void ReportWorkerTaskLoad(base::TimeTicks time, double load) { |
30 int load_percentage = static_cast<int>(load * 100); | 28 int load_percentage = static_cast<int>(load * 100); |
31 DCHECK_LE(load_percentage, 100); | 29 DCHECK_LE(load_percentage, 100); |
32 // TODO(kinuko): Maybe we also want to separately log when the associated | 30 // TODO(kinuko): Maybe we also want to separately log when the associated |
33 // tab is in foreground and when not. | 31 // tab is in foreground and when not. |
34 UMA_HISTOGRAM_PERCENTAGE("WorkerScheduler.WorkerThreadLoad", load_percentage); | 32 UMA_HISTOGRAM_PERCENTAGE("WorkerScheduler.WorkerThreadLoad", load_percentage); |
35 } | 33 } |
36 | 34 |
37 } // namespace | 35 } // namespace |
38 | 36 |
39 WorkerSchedulerImpl::WorkerSchedulerImpl( | 37 WorkerSchedulerImpl::WorkerSchedulerImpl( |
40 scoped_refptr<SchedulerTqmDelegate> main_task_runner) | 38 scoped_refptr<SchedulerTqmDelegate> main_task_runner) |
41 : WorkerScheduler(WTF::MakeUnique<SchedulerHelper>( | 39 : helper_(main_task_runner, |
42 main_task_runner, | 40 "worker.scheduler", |
43 "worker.scheduler", | 41 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), |
44 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), | 42 TRACE_DISABLED_BY_DEFAULT("worker.scheduler.debug")), |
45 TRACE_DISABLED_BY_DEFAULT("worker.scheduler.debug"))), | 43 idle_helper_(&helper_, |
46 idle_helper_(helper_.get(), | |
47 this, | 44 this, |
48 "worker.scheduler", | 45 "worker.scheduler", |
49 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), | 46 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), |
50 "WorkerSchedulerIdlePeriod", | 47 "WorkerSchedulerIdlePeriod", |
51 base::TimeDelta::FromMilliseconds(300)), | 48 base::TimeDelta::FromMilliseconds(300)), |
52 idle_canceled_delayed_task_sweeper_("worker.scheduler", | 49 idle_canceled_delayed_task_sweeper_("worker.scheduler", |
53 helper_.get(), | 50 &helper_, |
54 idle_helper_.IdleTaskRunner()), | 51 idle_helper_.IdleTaskRunner()), |
55 load_tracker_(helper_->scheduler_tqm_delegate()->NowTicks(), | 52 load_tracker_(helper_.scheduler_tqm_delegate()->NowTicks(), |
56 base::Bind(&ReportWorkerTaskLoad), | 53 base::Bind(&ReportWorkerTaskLoad), |
57 kWorkerThreadLoadTrackerReportingInterval, | 54 kWorkerThreadLoadTrackerReportingInterval, |
58 kWorkerThreadLoadTrackerWaitingPeriodBeforeReporting) { | 55 kWorkerThreadLoadTrackerWaitingPeriodBeforeReporting) { |
59 initialized_ = false; | 56 initialized_ = false; |
60 thread_start_time_ = helper_->scheduler_tqm_delegate()->NowTicks(); | 57 thread_start_time_ = helper_.scheduler_tqm_delegate()->NowTicks(); |
61 load_tracker_.Resume(thread_start_time_); | 58 load_tracker_.Resume(thread_start_time_); |
62 helper_->AddTaskTimeObserver(this); | 59 helper_.AddTaskTimeObserver(this); |
63 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | 60 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
64 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this); | 61 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this); |
65 } | 62 } |
66 | 63 |
67 WorkerSchedulerImpl::~WorkerSchedulerImpl() { | 64 WorkerSchedulerImpl::~WorkerSchedulerImpl() { |
68 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 65 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
69 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this); | 66 TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this); |
70 helper_->RemoveTaskTimeObserver(this); | 67 helper_.RemoveTaskTimeObserver(this); |
71 } | 68 } |
72 | 69 |
73 void WorkerSchedulerImpl::Init() { | 70 void WorkerSchedulerImpl::Init() { |
74 initialized_ = true; | 71 initialized_ = true; |
75 idle_helper_.EnableLongIdlePeriod(); | 72 idle_helper_.EnableLongIdlePeriod(); |
76 } | 73 } |
77 | 74 |
78 scoped_refptr<TaskQueue> WorkerSchedulerImpl::DefaultTaskRunner() { | 75 scoped_refptr<TaskQueue> WorkerSchedulerImpl::DefaultTaskRunner() { |
79 DCHECK(initialized_); | 76 DCHECK(initialized_); |
80 return helper_->DefaultTaskRunner(); | 77 return helper_.DefaultTaskRunner(); |
81 } | 78 } |
82 | 79 |
83 scoped_refptr<SingleThreadIdleTaskRunner> | 80 scoped_refptr<SingleThreadIdleTaskRunner> |
84 WorkerSchedulerImpl::IdleTaskRunner() { | 81 WorkerSchedulerImpl::IdleTaskRunner() { |
85 DCHECK(initialized_); | 82 DCHECK(initialized_); |
86 return idle_helper_.IdleTaskRunner(); | 83 return idle_helper_.IdleTaskRunner(); |
87 } | 84 } |
88 | 85 |
89 bool WorkerSchedulerImpl::CanExceedIdleDeadlineIfRequired() const { | 86 bool WorkerSchedulerImpl::CanExceedIdleDeadlineIfRequired() const { |
90 DCHECK(initialized_); | 87 DCHECK(initialized_); |
91 return idle_helper_.CanExceedIdleDeadlineIfRequired(); | 88 return idle_helper_.CanExceedIdleDeadlineIfRequired(); |
92 } | 89 } |
93 | 90 |
94 bool WorkerSchedulerImpl::ShouldYieldForHighPriorityWork() { | 91 bool WorkerSchedulerImpl::ShouldYieldForHighPriorityWork() { |
95 // We don't consider any work as being high priority on workers. | 92 // We don't consider any work as being high priority on workers. |
96 return false; | 93 return false; |
97 } | 94 } |
98 | 95 |
99 void WorkerSchedulerImpl::AddTaskObserver( | 96 void WorkerSchedulerImpl::AddTaskObserver( |
100 base::MessageLoop::TaskObserver* task_observer) { | 97 base::MessageLoop::TaskObserver* task_observer) { |
101 DCHECK(initialized_); | 98 DCHECK(initialized_); |
102 helper_->AddTaskObserver(task_observer); | 99 helper_.AddTaskObserver(task_observer); |
103 } | 100 } |
104 | 101 |
105 void WorkerSchedulerImpl::RemoveTaskObserver( | 102 void WorkerSchedulerImpl::RemoveTaskObserver( |
106 base::MessageLoop::TaskObserver* task_observer) { | 103 base::MessageLoop::TaskObserver* task_observer) { |
107 DCHECK(initialized_); | 104 DCHECK(initialized_); |
108 helper_->RemoveTaskObserver(task_observer); | 105 helper_.RemoveTaskObserver(task_observer); |
109 } | 106 } |
110 | 107 |
111 void WorkerSchedulerImpl::Shutdown() { | 108 void WorkerSchedulerImpl::Shutdown() { |
112 DCHECK(initialized_); | 109 DCHECK(initialized_); |
113 load_tracker_.RecordIdle(helper_->scheduler_tqm_delegate()->NowTicks()); | 110 load_tracker_.RecordIdle(helper_.scheduler_tqm_delegate()->NowTicks()); |
114 base::TimeTicks end_time = helper_->scheduler_tqm_delegate()->NowTicks(); | 111 base::TimeTicks end_time = helper_.scheduler_tqm_delegate()->NowTicks(); |
115 base::TimeDelta delta = end_time - thread_start_time_; | 112 base::TimeDelta delta = end_time - thread_start_time_; |
116 | 113 |
117 // The lifetime could be radically different for different workers, | 114 // The lifetime could be radically different for different workers, |
118 // some workers could be short-lived (but last at least 1 sec in | 115 // some workers could be short-lived (but last at least 1 sec in |
119 // Service Workers case) or could be around as long as the tab is open. | 116 // Service Workers case) or could be around as long as the tab is open. |
120 UMA_HISTOGRAM_CUSTOM_TIMES( | 117 UMA_HISTOGRAM_CUSTOM_TIMES( |
121 "WorkerThread.Runtime", delta, base::TimeDelta::FromSeconds(1), | 118 "WorkerThread.Runtime", delta, base::TimeDelta::FromSeconds(1), |
122 base::TimeDelta::FromDays(1), 50 /* bucket count */); | 119 base::TimeDelta::FromDays(1), 50 /* bucket count */); |
123 helper_->Shutdown(); | 120 helper_.Shutdown(); |
124 } | 121 } |
125 | 122 |
126 SchedulerHelper* WorkerSchedulerImpl::GetSchedulerHelperForTesting() { | 123 SchedulerHelper* WorkerSchedulerImpl::GetSchedulerHelperForTesting() { |
127 return helper_.get(); | 124 return &helper_; |
128 } | 125 } |
129 | 126 |
130 bool WorkerSchedulerImpl::CanEnterLongIdlePeriod(base::TimeTicks, | 127 bool WorkerSchedulerImpl::CanEnterLongIdlePeriod(base::TimeTicks, |
131 base::TimeDelta*) { | 128 base::TimeDelta*) { |
132 return true; | 129 return true; |
133 } | 130 } |
134 | 131 |
135 base::TimeTicks WorkerSchedulerImpl::CurrentIdleTaskDeadlineForTesting() const { | 132 base::TimeTicks WorkerSchedulerImpl::CurrentIdleTaskDeadlineForTesting() const { |
136 return idle_helper_.CurrentIdleTaskDeadline(); | 133 return idle_helper_.CurrentIdleTaskDeadline(); |
137 } | 134 } |
138 | 135 |
139 void WorkerSchedulerImpl::WillProcessTask(TaskQueue* task_queue, | 136 void WorkerSchedulerImpl::WillProcessTask(TaskQueue* task_queue, |
140 double start_time) {} | 137 double start_time) {} |
141 | 138 |
142 void WorkerSchedulerImpl::DidProcessTask(TaskQueue* task_queue, | 139 void WorkerSchedulerImpl::DidProcessTask(TaskQueue* task_queue, |
143 double start_time, | 140 double start_time, |
144 double end_time) { | 141 double end_time) { |
145 DEFINE_THREAD_SAFE_STATIC_LOCAL( | |
146 CustomCountHistogram, task_time_counter, | |
147 new CustomCountHistogram("WorkerThread.Task.Time", 0, 10000000, 50)); | |
148 task_time_counter.Count((end_time - start_time) * | |
149 base::Time::kMicrosecondsPerSecond); | |
150 | |
151 base::TimeTicks start_time_ticks = | 142 base::TimeTicks start_time_ticks = |
152 MonotonicTimeInSecondsToTimeTicks(start_time); | 143 MonotonicTimeInSecondsToTimeTicks(start_time); |
153 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); | 144 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); |
154 | 145 |
155 load_tracker_.RecordTaskTime(start_time_ticks, end_time_ticks); | 146 load_tracker_.RecordTaskTime(start_time_ticks, end_time_ticks); |
156 } | 147 } |
157 | 148 |
158 void WorkerSchedulerImpl::OnBeginNestedMessageLoop() {} | 149 void WorkerSchedulerImpl::OnBeginNestedMessageLoop() {} |
159 | 150 |
160 } // namespace scheduler | 151 } // namespace scheduler |
161 } // namespace blink | 152 } // namespace blink |
OLD | NEW |