Chromium Code Reviews| 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" |
| 19 #include "public/platform/scheduler/base/task_time_tracker.h" | |
| 20 | 20 |
| 21 namespace blink { | 21 namespace blink { |
| 22 namespace scheduler { | 22 namespace scheduler { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 const size_t kRecordRecordTaskDelayHistogramsEveryNTasks = 10; | 25 const size_t kRecordRecordTaskDelayHistogramsEveryNTasks = 10; |
| 26 | 26 |
| 27 void RecordDelayedTaskLateness(base::TimeDelta lateness) { | 27 void RecordDelayedTaskLateness(base::TimeDelta lateness) { |
| 28 UMA_HISTOGRAM_TIMES("RendererScheduler.TaskQueueManager.DelayedTaskLateness", | 28 UMA_HISTOGRAM_TIMES("RendererScheduler.TaskQueueManager.DelayedTaskLateness", |
| 29 lateness); | 29 lateness); |
| 30 } | 30 } |
| 31 | 31 |
| 32 void RecordImmediateTaskQueueingDuration(tracked_objects::Duration duration) { | 32 void RecordImmediateTaskQueueingDuration(tracked_objects::Duration duration) { |
| 33 UMA_HISTOGRAM_TIMES( | 33 UMA_HISTOGRAM_TIMES( |
| 34 "RendererScheduler.TaskQueueManager.ImmediateTaskQueueingDuration", | 34 "RendererScheduler.TaskQueueManager.ImmediateTaskQueueingDuration", |
| 35 base::TimeDelta::FromMilliseconds(duration.InMilliseconds())); | 35 base::TimeDelta::FromMilliseconds(duration.InMilliseconds())); |
| 36 } | 36 } |
| 37 | |
| 38 double MonotonicTimeInSeconds(base::TimeTicks timeTicks) { | |
| 39 return (timeTicks.ToInternalValue() / | |
|
alph
2016/08/22 23:51:07
nit: (timeTicks - base::TimeTicks()).InSecondsF()
panicker
2016/08/25 23:11:52
Done.
| |
| 40 static_cast<double>(base::Time::kMicrosecondsPerSecond)); | |
| 41 } | |
| 37 } | 42 } |
| 38 | 43 |
| 39 TaskQueueManager::TaskQueueManager( | 44 TaskQueueManager::TaskQueueManager( |
| 40 scoped_refptr<TaskQueueManagerDelegate> delegate, | 45 scoped_refptr<TaskQueueManagerDelegate> delegate, |
| 41 const char* tracing_category, | 46 const char* tracing_category, |
| 42 const char* disabled_by_default_tracing_category, | 47 const char* disabled_by_default_tracing_category, |
| 43 const char* disabled_by_default_verbose_tracing_category) | 48 const char* disabled_by_default_verbose_tracing_category) |
| 44 : real_time_domain_(new RealTimeDomain(tracing_category)), | 49 : real_time_domain_(new RealTimeDomain(tracing_category)), |
| 45 delegate_(delegate), | 50 delegate_(delegate), |
| 46 task_was_run_on_quiescence_monitored_queue_(false), | 51 task_was_run_on_quiescence_monitored_queue_(false), |
| 47 work_batch_size_(1), | 52 work_batch_size_(1), |
| 48 task_count_(0), | 53 task_count_(0), |
| 49 task_time_tracker_(nullptr), | |
| 50 tracing_category_(tracing_category), | 54 tracing_category_(tracing_category), |
| 51 disabled_by_default_tracing_category_( | 55 disabled_by_default_tracing_category_( |
| 52 disabled_by_default_tracing_category), | 56 disabled_by_default_tracing_category), |
| 53 disabled_by_default_verbose_tracing_category_( | 57 disabled_by_default_verbose_tracing_category_( |
| 54 disabled_by_default_verbose_tracing_category), | 58 disabled_by_default_verbose_tracing_category), |
| 55 currently_executing_task_queue_(nullptr), | 59 currently_executing_task_queue_(nullptr), |
| 56 observer_(nullptr), | 60 observer_(nullptr), |
| 57 deletion_sentinel_(new DeletionSentinel()), | 61 deletion_sentinel_(new DeletionSentinel()), |
| 58 weak_factory_(this) { | 62 weak_factory_(this) { |
| 59 DCHECK(delegate->RunsTasksOnCurrentThread()); | 63 DCHECK(delegate->RunsTasksOnCurrentThread()); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 190 base::AutoLock lock(other_thread_lock_); | 194 base::AutoLock lock(other_thread_lock_); |
| 191 other_thread_pending_wakeups_.erase(run_time); | 195 other_thread_pending_wakeups_.erase(run_time); |
| 192 } | 196 } |
| 193 | 197 |
| 194 if (!delegate_->IsNested()) | 198 if (!delegate_->IsNested()) |
| 195 queues_to_delete_.clear(); | 199 queues_to_delete_.clear(); |
| 196 | 200 |
| 197 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); | 201 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); |
| 198 base::TimeTicks task_start_time; | 202 base::TimeTicks task_start_time; |
| 199 | 203 |
| 200 if (!delegate_->IsNested() && task_time_tracker_) | 204 if (!delegate_->IsNested() && task_time_trackers_.might_have_observers()) |
| 201 task_start_time = lazy_now.Now(); | 205 task_start_time = lazy_now.Now(); |
| 202 | 206 |
| 203 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a | 207 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a |
| 204 // pump-after-wakeup queue. | 208 // pump-after-wakeup queue. |
| 205 UpdateWorkQueues(false, nullptr, lazy_now); | 209 UpdateWorkQueues(false, nullptr, lazy_now); |
| 206 | 210 |
| 207 internal::TaskQueueImpl::Task previous_task; | 211 internal::TaskQueueImpl::Task previous_task; |
| 208 | 212 |
| 209 for (int i = 0; i < work_batch_size_; i++) { | 213 for (int i = 0; i < work_batch_size_; i++) { |
| 210 internal::WorkQueue* work_queue; | 214 internal::WorkQueue* work_queue; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 221 // means deferred tasks (i.e. non-nestable tasks) will never trigger | 225 // means deferred tasks (i.e. non-nestable tasks) will never trigger |
| 222 // queue wake-ups. | 226 // queue wake-ups. |
| 223 continue; | 227 continue; |
| 224 case ProcessTaskResult::EXECUTED: | 228 case ProcessTaskResult::EXECUTED: |
| 225 break; | 229 break; |
| 226 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: | 230 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: |
| 227 return; // The TaskQueueManager got deleted, we must bail out. | 231 return; // The TaskQueueManager got deleted, we must bail out. |
| 228 } | 232 } |
| 229 | 233 |
| 230 lazy_now = real_time_domain()->CreateLazyNow(); | 234 lazy_now = real_time_domain()->CreateLazyNow(); |
| 231 if (!delegate_->IsNested() && task_time_tracker_) { | 235 if (!delegate_->IsNested() && task_time_trackers_.might_have_observers()) { |
| 232 // Only report top level task durations. | 236 // Only report top level task durations. |
| 233 base::TimeTicks task_end_time = lazy_now.Now(); | 237 base::TimeTicks task_end_time = lazy_now.Now(); |
| 234 task_time_tracker_->ReportTaskTime(task_start_time, task_end_time); | 238 FOR_EACH_OBSERVER(TaskTimeTracker, task_time_trackers_, |
| 239 ReportTaskTime(MonotonicTimeInSeconds(task_start_time), | |
| 240 MonotonicTimeInSeconds(task_end_time))); | |
| 235 task_start_time = task_end_time; | 241 task_start_time = task_end_time; |
|
alph
2016/08/22 23:51:07
Looks like the first time the observer will get a
panickercorp
2016/08/23 17:43:31
There can be an issue if there are 0 observers at
panicker
2016/08/25 23:11:52
I'm leaving this as is, as this is not worse than
Sami
2016/08/26 11:03:56
Sorry, I missed this question earlier. I think it
| |
| 236 } | 242 } |
| 237 | 243 |
| 238 work_queue = nullptr; // The queue may have been unregistered. | 244 work_queue = nullptr; // The queue may have been unregistered. |
| 239 | 245 |
| 240 UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); | 246 UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); |
| 241 | 247 |
| 242 // Only run a single task per batch in nested run loops so that we can | 248 // 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(). | 249 // properly exit the nested loop when someone calls RunLoop::Quit(). |
| 244 if (delegate_->IsNested()) | 250 if (delegate_->IsNested()) |
| 245 break; | 251 break; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 DCHECK(main_thread_checker_.CalledOnValidThread()); | 373 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 368 task_observers_.AddObserver(task_observer); | 374 task_observers_.AddObserver(task_observer); |
| 369 } | 375 } |
| 370 | 376 |
| 371 void TaskQueueManager::RemoveTaskObserver( | 377 void TaskQueueManager::RemoveTaskObserver( |
| 372 base::MessageLoop::TaskObserver* task_observer) { | 378 base::MessageLoop::TaskObserver* task_observer) { |
| 373 DCHECK(main_thread_checker_.CalledOnValidThread()); | 379 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 374 task_observers_.RemoveObserver(task_observer); | 380 task_observers_.RemoveObserver(task_observer); |
| 375 } | 381 } |
| 376 | 382 |
| 383 void TaskQueueManager::AddTaskTimeTracker(TaskTimeTracker* task_time_tracker) { | |
| 384 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 385 task_time_trackers_.AddObserver(task_time_tracker); | |
| 386 } | |
| 387 | |
| 388 void TaskQueueManager::RemoveTaskTimeTracker( | |
| 389 TaskTimeTracker* task_time_tracker) { | |
| 390 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 391 task_time_trackers_.RemoveObserver(task_time_tracker); | |
| 392 } | |
| 393 | |
| 377 bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() { | 394 bool TaskQueueManager::GetAndClearSystemIsQuiescentBit() { |
| 378 bool task_was_run = task_was_run_on_quiescence_monitored_queue_; | 395 bool task_was_run = task_was_run_on_quiescence_monitored_queue_; |
| 379 task_was_run_on_quiescence_monitored_queue_ = false; | 396 task_was_run_on_quiescence_monitored_queue_ = false; |
| 380 return !task_was_run; | 397 return !task_was_run; |
| 381 } | 398 } |
| 382 | 399 |
| 383 const scoped_refptr<TaskQueueManagerDelegate>& TaskQueueManager::delegate() | 400 const scoped_refptr<TaskQueueManagerDelegate>& TaskQueueManager::delegate() |
| 384 const { | 401 const { |
| 385 return delegate_; | 402 return delegate_; |
| 386 } | 403 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 434 DCHECK(main_thread_checker_.CalledOnValidThread()); | 451 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 435 DCHECK(!work_queue->Empty()); | 452 DCHECK(!work_queue->Empty()); |
| 436 if (observer_) { | 453 if (observer_) { |
| 437 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), | 454 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), |
| 438 *work_queue->GetFrontTask()); | 455 *work_queue->GetFrontTask()); |
| 439 } | 456 } |
| 440 } | 457 } |
| 441 | 458 |
| 442 } // namespace scheduler | 459 } // namespace scheduler |
| 443 } // namespace blink | 460 } // namespace blink |
| OLD | NEW |