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 "components/scheduler/base/task_queue_manager.h" | 5 #include "components/scheduler/base/task_queue_manager.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
12 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
13 #include "components/scheduler/base/real_time_domain.h" | 13 #include "components/scheduler/base/real_time_domain.h" |
14 #include "components/scheduler/base/task_queue_impl.h" | 14 #include "components/scheduler/base/task_queue_impl.h" |
15 #include "components/scheduler/base/task_queue_manager_delegate.h" | 15 #include "components/scheduler/base/task_queue_manager_delegate.h" |
16 #include "components/scheduler/base/task_queue_selector.h" | 16 #include "components/scheduler/base/task_queue_selector.h" |
17 #include "components/scheduler/base/task_time_tracker.h" | |
17 #include "components/scheduler/base/work_queue.h" | 18 #include "components/scheduler/base/work_queue.h" |
18 #include "components/scheduler/base/work_queue_sets.h" | 19 #include "components/scheduler/base/work_queue_sets.h" |
19 | 20 |
20 namespace scheduler { | 21 namespace scheduler { |
21 | 22 |
22 namespace { | 23 namespace { |
23 const size_t kRecordRecordTaskDelayHistogramsEveryNTasks = 10; | 24 const size_t kRecordRecordTaskDelayHistogramsEveryNTasks = 10; |
24 | 25 |
25 void RecordDelayedTaskLateness(base::TimeDelta lateness) { | 26 void RecordDelayedTaskLateness(base::TimeDelta lateness) { |
26 UMA_HISTOGRAM_TIMES("RendererScheduler.TaskQueueManager.DelayedTaskLateness", | 27 UMA_HISTOGRAM_TIMES("RendererScheduler.TaskQueueManager.DelayedTaskLateness", |
(...skipping 10 matching lines...) Expand all Loading... | |
37 TaskQueueManager::TaskQueueManager( | 38 TaskQueueManager::TaskQueueManager( |
38 scoped_refptr<TaskQueueManagerDelegate> delegate, | 39 scoped_refptr<TaskQueueManagerDelegate> delegate, |
39 const char* tracing_category, | 40 const char* tracing_category, |
40 const char* disabled_by_default_tracing_category, | 41 const char* disabled_by_default_tracing_category, |
41 const char* disabled_by_default_verbose_tracing_category) | 42 const char* disabled_by_default_verbose_tracing_category) |
42 : real_time_domain_(new RealTimeDomain(tracing_category)), | 43 : real_time_domain_(new RealTimeDomain(tracing_category)), |
43 delegate_(delegate), | 44 delegate_(delegate), |
44 task_was_run_on_quiescence_monitored_queue_(false), | 45 task_was_run_on_quiescence_monitored_queue_(false), |
45 work_batch_size_(1), | 46 work_batch_size_(1), |
46 task_count_(0), | 47 task_count_(0), |
48 task_time_tracker_(nullptr), | |
47 tracing_category_(tracing_category), | 49 tracing_category_(tracing_category), |
48 disabled_by_default_tracing_category_( | 50 disabled_by_default_tracing_category_( |
49 disabled_by_default_tracing_category), | 51 disabled_by_default_tracing_category), |
50 disabled_by_default_verbose_tracing_category_( | 52 disabled_by_default_verbose_tracing_category_( |
51 disabled_by_default_verbose_tracing_category), | 53 disabled_by_default_verbose_tracing_category), |
52 currently_executing_task_queue_(nullptr), | 54 currently_executing_task_queue_(nullptr), |
53 observer_(nullptr), | 55 observer_(nullptr), |
54 deletion_sentinel_(new DeletionSentinel()), | 56 deletion_sentinel_(new DeletionSentinel()), |
55 weak_factory_(this) { | 57 weak_factory_(this) { |
56 DCHECK(delegate->RunsTasksOnCurrentThread()); | 58 DCHECK(delegate->RunsTasksOnCurrentThread()); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 | 123 |
122 // Add |task_queue| to |queues_to_delete_| so we can prevent it from being | 124 // Add |task_queue| to |queues_to_delete_| so we can prevent it from being |
123 // freed while any of our structures hold hold a raw pointer to it. | 125 // freed while any of our structures hold hold a raw pointer to it. |
124 queues_to_delete_.insert(task_queue); | 126 queues_to_delete_.insert(task_queue); |
125 queues_.erase(task_queue); | 127 queues_.erase(task_queue); |
126 selector_.RemoveQueue(task_queue.get()); | 128 selector_.RemoveQueue(task_queue.get()); |
127 } | 129 } |
128 | 130 |
129 void TaskQueueManager::UpdateWorkQueues( | 131 void TaskQueueManager::UpdateWorkQueues( |
130 bool should_trigger_wakeup, | 132 bool should_trigger_wakeup, |
131 const internal::TaskQueueImpl::Task* previous_task) { | 133 const internal::TaskQueueImpl::Task* previous_task, |
134 LazyNow lazy_now) { | |
132 TRACE_EVENT0(disabled_by_default_tracing_category_, | 135 TRACE_EVENT0(disabled_by_default_tracing_category_, |
133 "TaskQueueManager::UpdateWorkQueues"); | 136 "TaskQueueManager::UpdateWorkQueues"); |
134 | 137 |
135 for (TimeDomain* time_domain : time_domains_) { | 138 for (TimeDomain* time_domain : time_domains_) { |
136 time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task); | 139 LazyNow lazy_now_in_domain = time_domain == real_time_domain_.get() |
140 ? lazy_now | |
141 : time_domain->CreateLazyNow(); | |
142 time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task, | |
143 lazy_now_in_domain); | |
137 } | 144 } |
138 } | 145 } |
139 | 146 |
140 void TaskQueueManager::MaybeScheduleImmediateWork( | 147 void TaskQueueManager::MaybeScheduleImmediateWork( |
141 const tracked_objects::Location& from_here) { | 148 const tracked_objects::Location& from_here) { |
142 bool on_main_thread = delegate_->BelongsToCurrentThread(); | 149 bool on_main_thread = delegate_->BelongsToCurrentThread(); |
143 // De-duplicate DoWork posts. | 150 // De-duplicate DoWork posts. |
144 if (on_main_thread) { | 151 if (on_main_thread) { |
145 if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second) { | 152 if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second) { |
146 return; | 153 return; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 if (from_main_thread) { | 187 if (from_main_thread) { |
181 main_thread_pending_wakeups_.erase(run_time); | 188 main_thread_pending_wakeups_.erase(run_time); |
182 } else { | 189 } else { |
183 base::AutoLock lock(other_thread_lock_); | 190 base::AutoLock lock(other_thread_lock_); |
184 other_thread_pending_wakeups_.erase(run_time); | 191 other_thread_pending_wakeups_.erase(run_time); |
185 } | 192 } |
186 | 193 |
187 if (!delegate_->IsNested()) | 194 if (!delegate_->IsNested()) |
188 queues_to_delete_.clear(); | 195 queues_to_delete_.clear(); |
189 | 196 |
197 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); | |
198 base::TimeTicks task_start_time; | |
199 | |
200 if (!delegate_->IsNested() && task_time_tracker_) | |
201 task_start_time = lazy_now.Now(); | |
202 | |
190 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a | 203 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a |
191 // pump-after-wakeup queue. | 204 // pump-after-wakeup queue. |
192 UpdateWorkQueues(false, nullptr); | 205 UpdateWorkQueues(false, nullptr, lazy_now); |
193 | 206 |
194 internal::TaskQueueImpl::Task previous_task; | 207 internal::TaskQueueImpl::Task previous_task; |
208 | |
195 for (int i = 0; i < work_batch_size_; i++) { | 209 for (int i = 0; i < work_batch_size_; i++) { |
196 internal::WorkQueue* work_queue; | 210 internal::WorkQueue* work_queue; |
197 if (!SelectWorkQueueToService(&work_queue)) { | 211 if (!SelectWorkQueueToService(&work_queue)) { |
198 break; | 212 break; |
199 } | 213 } |
200 | 214 |
201 bool should_trigger_wakeup = work_queue->task_queue()->wakeup_policy() == | 215 bool should_trigger_wakeup = work_queue->task_queue()->wakeup_policy() == |
202 TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES; | 216 TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES; |
217 | |
203 switch (ProcessTaskFromWorkQueue(work_queue, &previous_task)) { | 218 switch (ProcessTaskFromWorkQueue(work_queue, &previous_task)) { |
204 case ProcessTaskResult::DEFERRED: | 219 case ProcessTaskResult::DEFERRED: |
205 // If a task was deferred, try again with another task. Note that this | 220 // If a task was deferred, try again with another task. Note that this |
206 // means deferred tasks (i.e. non-nestable tasks) will never trigger | 221 // means deferred tasks (i.e. non-nestable tasks) will never trigger |
207 // queue wake-ups. | 222 // queue wake-ups. |
208 continue; | 223 continue; |
209 case ProcessTaskResult::EXECUTED: | 224 case ProcessTaskResult::EXECUTED: |
210 break; | 225 break; |
211 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: | 226 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: |
212 return; // The TaskQueueManager got deleted, we must bail out. | 227 return; // The TaskQueueManager got deleted, we must bail out. |
213 } | 228 } |
229 | |
230 lazy_now = real_time_domain()->CreateLazyNow(); | |
231 if (!delegate_->IsNested() && task_time_tracker_) { | |
232 // Only report top level task durations. | |
233 base::TimeTicks task_end_time = real_time_domain()->Now(); | |
alex clarke (OOO till 29th)
2016/07/06 09:51:39
Can you do this?
if (!delegate_->IsNested() && ta
tdresser
2016/07/06 13:25:34
Done.
| |
234 task_time_tracker_->ReportTaskTime(task_start_time, task_end_time); | |
235 task_start_time = task_end_time; | |
236 lazy_now = LazyNow(task_end_time); | |
237 } | |
238 | |
214 work_queue = nullptr; // The queue may have been unregistered. | 239 work_queue = nullptr; // The queue may have been unregistered. |
215 | 240 |
216 UpdateWorkQueues(should_trigger_wakeup, &previous_task); | 241 UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); |
217 | 242 |
218 // Only run a single task per batch in nested run loops so that we can | 243 // Only run a single task per batch in nested run loops so that we can |
219 // properly exit the nested loop when someone calls RunLoop::Quit(). | 244 // properly exit the nested loop when someone calls RunLoop::Quit(). |
220 if (delegate_->IsNested()) | 245 if (delegate_->IsNested()) |
221 break; | 246 break; |
222 } | 247 } |
223 | 248 |
224 // TODO(alexclarke): Consider refactoring the above loop to terminate only | 249 // TODO(alexclarke): Consider refactoring the above loop to terminate only |
225 // when there's no more work left to be done, rather than posting a | 250 // when there's no more work left to be done, rather than posting a |
226 // continuation task. | 251 // continuation task. |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 internal::WorkQueue* work_queue) { | 434 internal::WorkQueue* work_queue) { |
410 DCHECK(main_thread_checker_.CalledOnValidThread()); | 435 DCHECK(main_thread_checker_.CalledOnValidThread()); |
411 DCHECK(!work_queue->Empty()); | 436 DCHECK(!work_queue->Empty()); |
412 if (observer_) { | 437 if (observer_) { |
413 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), | 438 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), |
414 *work_queue->GetFrontTask()); | 439 *work_queue->GetFrontTask()); |
415 } | 440 } |
416 } | 441 } |
417 | 442 |
418 } // namespace scheduler | 443 } // namespace scheduler |
OLD | NEW |