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/base/task_queue_manager.h" | 5 #include "platform/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 "platform/scheduler/base/real_time_domain.h" | 13 #include "platform/scheduler/base/real_time_domain.h" |
14 #include "platform/scheduler/base/task_queue_impl.h" | 14 #include "platform/scheduler/base/task_queue_impl.h" |
15 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 15 #include "platform/scheduler/base/task_queue_manager_delegate.h" |
16 #include "platform/scheduler/base/task_queue_selector.h" | 16 #include "platform/scheduler/base/task_queue_selector.h" |
17 #include "platform/scheduler/base/task_time_tracker.h" | |
18 #include "platform/scheduler/base/work_queue.h" | 17 #include "platform/scheduler/base/work_queue.h" |
19 #include "platform/scheduler/base/work_queue_sets.h" | 18 #include "platform/scheduler/base/work_queue_sets.h" |
20 | 19 |
21 namespace blink { | 20 namespace blink { |
22 namespace scheduler { | 21 namespace scheduler { |
23 | 22 |
24 namespace { | 23 namespace { |
25 const size_t kRecordRecordTaskDelayHistogramsEveryNTasks = 10; | 24 const size_t kRecordRecordTaskDelayHistogramsEveryNTasks = 10; |
26 | 25 |
27 void RecordDelayedTaskLateness(base::TimeDelta lateness) { | 26 void RecordDelayedTaskLateness(base::TimeDelta lateness) { |
28 UMA_HISTOGRAM_TIMES("RendererScheduler.TaskQueueManager.DelayedTaskLateness", | 27 UMA_HISTOGRAM_TIMES("RendererScheduler.TaskQueueManager.DelayedTaskLateness", |
29 lateness); | 28 lateness); |
30 } | 29 } |
31 | 30 |
32 void RecordImmediateTaskQueueingDuration(tracked_objects::Duration duration) { | 31 void RecordImmediateTaskQueueingDuration(tracked_objects::Duration duration) { |
33 UMA_HISTOGRAM_TIMES( | 32 UMA_HISTOGRAM_TIMES( |
34 "RendererScheduler.TaskQueueManager.ImmediateTaskQueueingDuration", | 33 "RendererScheduler.TaskQueueManager.ImmediateTaskQueueingDuration", |
35 base::TimeDelta::FromMilliseconds(duration.InMilliseconds())); | 34 base::TimeDelta::FromMilliseconds(duration.InMilliseconds())); |
36 } | 35 } |
36 | |
37 double MonotonicTimeInSeconds(base::TimeTicks timeTicks) { | |
caseq
2016/08/22 18:48:49
WTF::monotonicallyIncreasingTime()?
panicker
2016/08/22 23:14:14
I'm trying to convert the provided timeTicks, not
| |
38 return (timeTicks.ToInternalValue() / static_cast<double>( | |
39 base::Time::kMicrosecondsPerSecond)); | |
40 } | |
37 } | 41 } |
38 | 42 |
39 TaskQueueManager::TaskQueueManager( | 43 TaskQueueManager::TaskQueueManager( |
40 scoped_refptr<TaskQueueManagerDelegate> delegate, | 44 scoped_refptr<TaskQueueManagerDelegate> delegate, |
41 const char* tracing_category, | 45 const char* tracing_category, |
42 const char* disabled_by_default_tracing_category, | 46 const char* disabled_by_default_tracing_category, |
43 const char* disabled_by_default_verbose_tracing_category) | 47 const char* disabled_by_default_verbose_tracing_category) |
44 : real_time_domain_(new RealTimeDomain(tracing_category)), | 48 : real_time_domain_(new RealTimeDomain(tracing_category)), |
45 delegate_(delegate), | 49 delegate_(delegate), |
46 task_was_run_on_quiescence_monitored_queue_(false), | 50 task_was_run_on_quiescence_monitored_queue_(false), |
47 work_batch_size_(1), | 51 work_batch_size_(1), |
48 task_count_(0), | 52 task_count_(0), |
49 task_time_tracker_(nullptr), | |
50 tracing_category_(tracing_category), | 53 tracing_category_(tracing_category), |
51 disabled_by_default_tracing_category_( | 54 disabled_by_default_tracing_category_( |
52 disabled_by_default_tracing_category), | 55 disabled_by_default_tracing_category), |
53 disabled_by_default_verbose_tracing_category_( | 56 disabled_by_default_verbose_tracing_category_( |
54 disabled_by_default_verbose_tracing_category), | 57 disabled_by_default_verbose_tracing_category), |
55 currently_executing_task_queue_(nullptr), | 58 currently_executing_task_queue_(nullptr), |
56 observer_(nullptr), | 59 observer_(nullptr), |
57 deletion_sentinel_(new DeletionSentinel()), | 60 deletion_sentinel_(new DeletionSentinel()), |
58 weak_factory_(this) { | 61 weak_factory_(this) { |
59 DCHECK(delegate->RunsTasksOnCurrentThread()); | 62 DCHECK(delegate->RunsTasksOnCurrentThread()); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 base::AutoLock lock(other_thread_lock_); | 193 base::AutoLock lock(other_thread_lock_); |
191 other_thread_pending_wakeups_.erase(run_time); | 194 other_thread_pending_wakeups_.erase(run_time); |
192 } | 195 } |
193 | 196 |
194 if (!delegate_->IsNested()) | 197 if (!delegate_->IsNested()) |
195 queues_to_delete_.clear(); | 198 queues_to_delete_.clear(); |
196 | 199 |
197 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); | 200 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); |
198 base::TimeTicks task_start_time; | 201 base::TimeTicks task_start_time; |
199 | 202 |
200 if (!delegate_->IsNested() && task_time_tracker_) | 203 if (!delegate_->IsNested() && task_time_observers_.might_have_observers() > 0) |
201 task_start_time = lazy_now.Now(); | 204 task_start_time = lazy_now.Now(); |
202 | 205 |
203 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a | 206 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a |
204 // pump-after-wakeup queue. | 207 // pump-after-wakeup queue. |
205 UpdateWorkQueues(false, nullptr, lazy_now); | 208 UpdateWorkQueues(false, nullptr, lazy_now); |
206 | 209 |
207 internal::TaskQueueImpl::Task previous_task; | 210 internal::TaskQueueImpl::Task previous_task; |
208 | 211 |
209 for (int i = 0; i < work_batch_size_; i++) { | 212 for (int i = 0; i < work_batch_size_; i++) { |
210 internal::WorkQueue* work_queue; | 213 internal::WorkQueue* work_queue; |
211 if (!SelectWorkQueueToService(&work_queue)) { | 214 if (!SelectWorkQueueToService(&work_queue)) { |
212 break; | 215 break; |
213 } | 216 } |
214 | 217 |
215 bool should_trigger_wakeup = work_queue->task_queue()->wakeup_policy() == | 218 bool should_trigger_wakeup = work_queue->task_queue()->wakeup_policy() == |
216 TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES; | 219 TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES; |
217 | 220 |
218 switch (ProcessTaskFromWorkQueue(work_queue, &previous_task)) { | 221 |
222 if (!delegate_->IsNested()) { | |
223 FOR_EACH_OBSERVER(WebThread::TaskTimeObserver, task_time_observers_, | |
Sami
2016/08/22 15:51:30
(Indentation looks a little off -- git cl format s
panicker
2016/08/22 23:14:14
Done.
| |
224 willProcessTask()); | |
225 } | |
226 TaskQueueManager::ProcessTaskResult result = ProcessTaskFromWorkQueue( | |
227 work_queue, &previous_task); | |
228 if (!delegate_->IsNested()) { | |
229 FOR_EACH_OBSERVER(WebThread::TaskTimeObserver, task_time_observers_, | |
caseq
2016/08/22 18:48:49
Have you considered moving this into ProcessTaskFr
panicker
2016/08/22 23:14:14
Addressed in new patch.
Sami had the same comment
| |
230 didProcessTask()); | |
231 } | |
232 | |
233 switch (result) { | |
219 case ProcessTaskResult::DEFERRED: | 234 case ProcessTaskResult::DEFERRED: |
220 // If a task was deferred, try again with another task. Note that this | 235 // If a task was deferred, try again with another task. Note that this |
221 // means deferred tasks (i.e. non-nestable tasks) will never trigger | 236 // means deferred tasks (i.e. non-nestable tasks) will never trigger |
222 // queue wake-ups. | 237 // queue wake-ups. |
223 continue; | 238 continue; |
224 case ProcessTaskResult::EXECUTED: | 239 case ProcessTaskResult::EXECUTED: |
225 break; | 240 break; |
226 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: | 241 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: |
227 return; // The TaskQueueManager got deleted, we must bail out. | 242 return; // The TaskQueueManager got deleted, we must bail out. |
228 } | 243 } |
229 | 244 |
230 lazy_now = real_time_domain()->CreateLazyNow(); | 245 lazy_now = real_time_domain()->CreateLazyNow(); |
231 if (!delegate_->IsNested() && task_time_tracker_) { | 246 if (!delegate_->IsNested() && task_time_observers_.might_have_observers()) { |
232 // Only report top level task durations. | 247 // Only report top level task durations. |
233 base::TimeTicks task_end_time = lazy_now.Now(); | 248 base::TimeTicks task_end_time = lazy_now.Now(); |
234 task_time_tracker_->ReportTaskTime(task_start_time, task_end_time); | 249 FOR_EACH_OBSERVER( |
250 WebThread::TaskTimeObserver, task_time_observers_, reportTaskTime( | |
251 MonotonicTimeInSeconds(task_start_time), | |
252 MonotonicTimeInSeconds(task_end_time))); | |
235 task_start_time = task_end_time; | 253 task_start_time = task_end_time; |
236 } | 254 } |
237 | 255 |
238 work_queue = nullptr; // The queue may have been unregistered. | 256 work_queue = nullptr; // The queue may have been unregistered. |
239 | 257 |
240 UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); | 258 UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); |
241 | 259 |
242 // Only run a single task per batch in nested run loops so that we can | 260 // Only run a single task per batch in nested run loops so that we can |
243 // properly exit the nested loop when someone calls RunLoop::Quit(). | 261 // properly exit the nested loop when someone calls RunLoop::Quit(). |
244 if (delegate_->IsNested()) | 262 if (delegate_->IsNested()) |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 DCHECK(main_thread_checker_.CalledOnValidThread()); | 385 DCHECK(main_thread_checker_.CalledOnValidThread()); |
368 task_observers_.AddObserver(task_observer); | 386 task_observers_.AddObserver(task_observer); |
369 } | 387 } |
370 | 388 |
371 void TaskQueueManager::RemoveTaskObserver( | 389 void TaskQueueManager::RemoveTaskObserver( |
372 base::MessageLoop::TaskObserver* task_observer) { | 390 base::MessageLoop::TaskObserver* task_observer) { |
373 DCHECK(main_thread_checker_.CalledOnValidThread()); | 391 DCHECK(main_thread_checker_.CalledOnValidThread()); |
374 task_observers_.RemoveObserver(task_observer); | 392 task_observers_.RemoveObserver(task_observer); |
375 } | 393 } |
376 | 394 |
395 void TaskQueueManager::AddTaskTimeObserver( | |
396 WebThread::TaskTimeObserver* task_time_observer) { | |
397 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
398 task_time_observers_.AddObserver(task_time_observer); | |
alph
2016/08/22 22:21:27
nit: You could also add it into task_observers_, s
panicker
2016/08/22 23:14:14
yep - done in new patch.
| |
399 } | |
400 | |
401 void TaskQueueManager::RemoveTaskTimeObserver( | |
402 WebThread::TaskTimeObserver* task_time_observer) { | |
403 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
404 task_time_observers_.RemoveObserver(task_time_observer); | |
405 } | |
406 | |
377 bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() { | 407 bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() { |
378 bool task_was_run = task_was_run_on_quiescence_monitored_queue_; | 408 bool task_was_run = task_was_run_on_quiescence_monitored_queue_; |
379 task_was_run_on_quiescence_monitored_queue_ = false; | 409 task_was_run_on_quiescence_monitored_queue_ = false; |
380 return !task_was_run; | 410 return !task_was_run; |
381 } | 411 } |
382 | 412 |
383 const scoped_refptr<TaskQueueManagerDelegate>& TaskQueueManager::delegate() | 413 const scoped_refptr<TaskQueueManagerDelegate>& TaskQueueManager::delegate() |
384 const { | 414 const { |
385 return delegate_; | 415 return delegate_; |
386 } | 416 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 DCHECK(main_thread_checker_.CalledOnValidThread()); | 464 DCHECK(main_thread_checker_.CalledOnValidThread()); |
435 DCHECK(!work_queue->Empty()); | 465 DCHECK(!work_queue->Empty()); |
436 if (observer_) { | 466 if (observer_) { |
437 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), | 467 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), |
438 *work_queue->GetFrontTask()); | 468 *work_queue->GetFrontTask()); |
439 } | 469 } |
440 } | 470 } |
441 | 471 |
442 } // namespace scheduler | 472 } // namespace scheduler |
443 } // namespace blink | 473 } // namespace blink |
OLD | NEW |