Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "base/task_scheduler/scheduler_worker_pool_impl.h" | 5 #include "base/task_scheduler/scheduler_worker_pool_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "base/time/time.h" | 27 #include "base/time/time.h" |
| 28 | 28 |
| 29 namespace base { | 29 namespace base { |
| 30 namespace internal { | 30 namespace internal { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 constexpr char kPoolNameSuffix[] = "Pool"; | 34 constexpr char kPoolNameSuffix[] = "Pool"; |
| 35 constexpr char kDetachDurationHistogramPrefix[] = | 35 constexpr char kDetachDurationHistogramPrefix[] = |
| 36 "TaskScheduler.DetachDuration."; | 36 "TaskScheduler.DetachDuration."; |
| 37 constexpr char kNumTasksBeforeDetachHistogramPrefix[] = | |
| 38 "TaskScheduler.NumTasksBeforeDetach."; | |
| 37 constexpr char kNumTasksBetweenWaitsHistogramPrefix[] = | 39 constexpr char kNumTasksBetweenWaitsHistogramPrefix[] = |
| 38 "TaskScheduler.NumTasksBetweenWaits."; | 40 "TaskScheduler.NumTasksBetweenWaits."; |
| 39 constexpr char kTaskLatencyHistogramPrefix[] = "TaskScheduler.TaskLatency."; | 41 constexpr char kTaskLatencyHistogramPrefix[] = "TaskScheduler.TaskLatency."; |
| 40 | 42 |
| 41 // SchedulerWorker that owns the current thread, if any. | 43 // SchedulerWorker that owns the current thread, if any. |
| 42 LazyInstance<ThreadLocalPointer<const SchedulerWorker>>::Leaky | 44 LazyInstance<ThreadLocalPointer<const SchedulerWorker>>::Leaky |
| 43 tls_current_worker = LAZY_INSTANCE_INITIALIZER; | 45 tls_current_worker = LAZY_INSTANCE_INITIALIZER; |
| 44 | 46 |
| 45 // SchedulerWorkerPool that owns the current thread, if any. | 47 // SchedulerWorkerPool that owns the current thread, if any. |
| 46 LazyInstance<ThreadLocalPointer<const SchedulerWorkerPool>>::Leaky | 48 LazyInstance<ThreadLocalPointer<const SchedulerWorkerPool>>::Leaky |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 bool last_get_work_returned_nullptr_ = false; | 275 bool last_get_work_returned_nullptr_ = false; |
| 274 | 276 |
| 275 // Indicates whether the SchedulerWorker was detached since the last call to | 277 // Indicates whether the SchedulerWorker was detached since the last call to |
| 276 // GetWork(). | 278 // GetWork(). |
| 277 bool did_detach_since_last_get_work_ = false; | 279 bool did_detach_since_last_get_work_ = false; |
| 278 | 280 |
| 279 // Number of tasks executed since the last time the | 281 // Number of tasks executed since the last time the |
| 280 // TaskScheduler.NumTasksBetweenWaits histogram was recorded. | 282 // TaskScheduler.NumTasksBetweenWaits histogram was recorded. |
| 281 size_t num_tasks_since_last_wait_ = 0; | 283 size_t num_tasks_since_last_wait_ = 0; |
| 282 | 284 |
| 285 // Number of tasks executed since the last time the | |
| 286 // TaskScheduler.NumTasksBeforeDetach histogram was recorded. | |
| 287 size_t num_tasks_since_last_detach_ = 0; | |
| 288 | |
| 283 subtle::Atomic32 num_single_threaded_runners_ = 0; | 289 subtle::Atomic32 num_single_threaded_runners_ = 0; |
| 284 | 290 |
| 285 const int index_; | 291 const int index_; |
| 286 | 292 |
| 287 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegateImpl); | 293 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegateImpl); |
| 288 }; | 294 }; |
| 289 | 295 |
| 290 SchedulerWorkerPoolImpl::~SchedulerWorkerPoolImpl() { | 296 SchedulerWorkerPoolImpl::~SchedulerWorkerPoolImpl() { |
| 291 // SchedulerWorkerPool should never be deleted in production unless its | 297 // SchedulerWorkerPool should never be deleted in production unless its |
| 292 // initialization failed. | 298 // initialization failed. |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 const TimeDelta& detach_duration) { | 485 const TimeDelta& detach_duration) { |
| 480 #if DCHECK_IS_ON() | 486 #if DCHECK_IS_ON() |
| 481 // Wait for |outer_->workers_created_| to avoid traversing | 487 // Wait for |outer_->workers_created_| to avoid traversing |
| 482 // |outer_->workers_| while it is being filled by Initialize(). | 488 // |outer_->workers_| while it is being filled by Initialize(). |
| 483 outer_->workers_created_.Wait(); | 489 outer_->workers_created_.Wait(); |
| 484 DCHECK(ContainsWorker(outer_->workers_, worker)); | 490 DCHECK(ContainsWorker(outer_->workers_, worker)); |
| 485 #endif | 491 #endif |
| 486 | 492 |
| 487 DCHECK_EQ(num_tasks_since_last_wait_, 0U); | 493 DCHECK_EQ(num_tasks_since_last_wait_, 0U); |
| 488 | 494 |
| 495 // Record histograms if the worker detached in the past. | |
| 489 if (!detach_duration.is_max()) { | 496 if (!detach_duration.is_max()) { |
| 490 outer_->detach_duration_histogram_->AddTime(detach_duration); | 497 outer_->detach_duration_histogram_->AddTime(detach_duration); |
| 498 outer_->num_tasks_before_detach_histogram_->Add( | |
|
gab
2016/10/17 18:24:00
Recording here will only record if the thread is r
robliao
2016/10/17 23:05:39
The SchedulerWorker is free to ignore the detach r
gab
2016/10/18 14:45:45
Right but we could still add SchedulerWorkerDelega
fdoray
2016/10/18 19:41:22
Done.
| |
| 499 num_tasks_since_last_detach_); | |
| 500 num_tasks_since_last_detach_ = 0; | |
| 491 did_detach_since_last_get_work_ = true; | 501 did_detach_since_last_get_work_ = true; |
| 492 } | 502 } |
| 493 | 503 |
| 494 PlatformThread::SetName( | 504 PlatformThread::SetName( |
| 495 StringPrintf("TaskScheduler%sWorker%d", outer_->name_.c_str(), index_)); | 505 StringPrintf("TaskScheduler%sWorker%d", outer_->name_.c_str(), index_)); |
| 496 | 506 |
| 497 DCHECK(!tls_current_worker.Get().Get()); | 507 DCHECK(!tls_current_worker.Get().Get()); |
| 498 DCHECK(!tls_current_worker_pool.Get().Get()); | 508 DCHECK(!tls_current_worker_pool.Get().Get()); |
| 499 tls_current_worker.Get().Set(worker); | 509 tls_current_worker.Get().Set(worker); |
| 500 tls_current_worker_pool.Get().Set(outer_); | 510 tls_current_worker_pool.Get().Set(outer_); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 did_detach_since_last_get_work_ = false; | 596 did_detach_since_last_get_work_ = false; |
| 587 last_get_work_returned_nullptr_ = false; | 597 last_get_work_returned_nullptr_ = false; |
| 588 | 598 |
| 589 return sequence; | 599 return sequence; |
| 590 } | 600 } |
| 591 | 601 |
| 592 void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl:: | 602 void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl:: |
| 593 DidRunTaskWithPriority(TaskPriority task_priority, | 603 DidRunTaskWithPriority(TaskPriority task_priority, |
| 594 const TimeDelta& task_latency) { | 604 const TimeDelta& task_latency) { |
| 595 ++num_tasks_since_last_wait_; | 605 ++num_tasks_since_last_wait_; |
| 606 ++num_tasks_since_last_detach_; | |
| 596 | 607 |
| 597 const int priority_index = static_cast<int>(task_priority); | 608 const int priority_index = static_cast<int>(task_priority); |
| 598 | 609 |
| 599 // As explained in the header file, histograms are allocated on demand. It | 610 // As explained in the header file, histograms are allocated on demand. It |
| 600 // doesn't matter if an element of |task_latency_histograms_| is set multiple | 611 // doesn't matter if an element of |task_latency_histograms_| is set multiple |
| 601 // times since GetTaskLatencyHistogram() is idempotent. As explained in the | 612 // times since GetTaskLatencyHistogram() is idempotent. As explained in the |
| 602 // comment at the top of histogram_macros.h, barriers are required. | 613 // comment at the top of histogram_macros.h, barriers are required. |
| 603 HistogramBase* task_latency_histogram = reinterpret_cast<HistogramBase*>( | 614 HistogramBase* task_latency_histogram = reinterpret_cast<HistogramBase*>( |
| 604 subtle::Acquire_Load(&outer_->task_latency_histograms_[priority_index])); | 615 subtle::Acquire_Load(&outer_->task_latency_histograms_[priority_index])); |
| 605 if (!task_latency_histogram) { | 616 if (!task_latency_histogram) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 666 workers_created_(WaitableEvent::ResetPolicy::MANUAL, | 677 workers_created_(WaitableEvent::ResetPolicy::MANUAL, |
| 667 WaitableEvent::InitialState::NOT_SIGNALED), | 678 WaitableEvent::InitialState::NOT_SIGNALED), |
| 668 #endif | 679 #endif |
| 669 // Mimics the UMA_HISTOGRAM_LONG_TIMES macro. | 680 // Mimics the UMA_HISTOGRAM_LONG_TIMES macro. |
| 670 detach_duration_histogram_(Histogram::FactoryTimeGet( | 681 detach_duration_histogram_(Histogram::FactoryTimeGet( |
| 671 kDetachDurationHistogramPrefix + name_ + kPoolNameSuffix, | 682 kDetachDurationHistogramPrefix + name_ + kPoolNameSuffix, |
| 672 TimeDelta::FromMilliseconds(1), | 683 TimeDelta::FromMilliseconds(1), |
| 673 TimeDelta::FromHours(1), | 684 TimeDelta::FromHours(1), |
| 674 50, | 685 50, |
| 675 HistogramBase::kUmaTargetedHistogramFlag)), | 686 HistogramBase::kUmaTargetedHistogramFlag)), |
| 687 // Mimics the UMA_HISTOGRAM_COUNTS_1000 macro. A SchedulerWorker is | |
| 688 // expected to run between zero and a few hundreds of tasks before | |
| 689 // detaching. When it runs more than 1000 tasks, there is no need to know | |
| 690 // the exact number of tasks that ran. | |
|
gab
2016/10/17 18:24:00
While I agree that once it runs more than a 1000 t
fdoray
2016/10/18 19:41:22
Done.
| |
| 691 num_tasks_before_detach_histogram_(Histogram::FactoryGet( | |
| 692 kNumTasksBeforeDetachHistogramPrefix + name_ + kPoolNameSuffix, | |
| 693 1, | |
| 694 1000, | |
| 695 50, | |
| 696 HistogramBase::kUmaTargetedHistogramFlag)), | |
| 676 // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A SchedulerWorker is | 697 // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A SchedulerWorker is |
| 677 // expected to run between zero and a few tens of tasks between waits. | 698 // expected to run between zero and a few tens of tasks between waits. |
| 678 // When it runs more than 100 tasks, there is no need to know the exact | 699 // When it runs more than 100 tasks, there is no need to know the exact |
| 679 // number of tasks that ran. | 700 // number of tasks that ran. |
| 680 num_tasks_between_waits_histogram_(Histogram::FactoryGet( | 701 num_tasks_between_waits_histogram_(Histogram::FactoryGet( |
| 681 kNumTasksBetweenWaitsHistogramPrefix + name_ + kPoolNameSuffix, | 702 kNumTasksBetweenWaitsHistogramPrefix + name_ + kPoolNameSuffix, |
| 682 1, | 703 1, |
| 683 100, | 704 100, |
| 684 50, | 705 50, |
| 685 HistogramBase::kUmaTargetedHistogramFlag)), | 706 HistogramBase::kUmaTargetedHistogramFlag)), |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); | 786 AutoSchedulerLock auto_lock(idle_workers_stack_lock_); |
| 766 idle_workers_stack_.Remove(worker); | 787 idle_workers_stack_.Remove(worker); |
| 767 } | 788 } |
| 768 | 789 |
| 769 bool SchedulerWorkerPoolImpl::CanWorkerDetachForTesting() { | 790 bool SchedulerWorkerPoolImpl::CanWorkerDetachForTesting() { |
| 770 return !worker_detachment_disallowed_.IsSet(); | 791 return !worker_detachment_disallowed_.IsSet(); |
| 771 } | 792 } |
| 772 | 793 |
| 773 } // namespace internal | 794 } // namespace internal |
| 774 } // namespace base | 795 } // namespace base |
| OLD | NEW |