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