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/task_scheduler_impl.h" | 5 #include "base/task_scheduler/task_scheduler_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 7 #include <utility> | 8 #include <utility> |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/logging.h" | |
| 11 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | |
| 15 #include "base/sys_info.h" | |
| 12 #include "base/task_scheduler/scheduler_service_thread.h" | 16 #include "base/task_scheduler/scheduler_service_thread.h" |
| 13 #include "base/task_scheduler/scheduler_thread_pool_impl.h" | 17 #include "base/task_scheduler/scheduler_thread_pool_impl.h" |
| 14 #include "base/task_scheduler/sequence_sort_key.h" | 18 #include "base/task_scheduler/sequence_sort_key.h" |
| 15 #include "base/task_scheduler/task.h" | 19 #include "base/task_scheduler/task.h" |
| 16 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 17 | 21 |
| 18 namespace base { | 22 namespace base { |
| 19 namespace internal { | 23 namespace internal { |
| 20 | 24 |
| 25 namespace { | |
| 26 | |
| 27 constexpr char kTaskSchedulerThreadNamePrefix[] = "TaskScheduler"; | |
| 28 | |
| 29 struct ThreadPoolSettings { | |
| 30 // Name of the pool. Used to name threads and to find variation params that | |
| 31 // apply to this pool. | |
| 32 const char* name; | |
| 33 | |
| 34 // Default values used to compute the maximum number of threads in the pool | |
| 35 // (used when not specified by variation params). | |
| 36 int default_min_threads; | |
|
robliao
2016/06/14 21:43:44
uint32_t might be more appropriate.
fdoray
2016/06/15 17:14:32
Does this rule apply here?
"You should not use the
robliao
2016/06/15 17:32:37
Hrm... interesting. I guess we'll stick with that
| |
| 37 int default_max_threads; | |
| 38 int default_threads_percentage_num_processors; | |
| 39 }; | |
| 40 | |
| 41 constexpr ThreadPoolSettings kBackgroundPoolSettings{"Background", 1, 1, 0}; | |
|
robliao
2016/06/14 21:43:44
This shouldn't trigger a static init, right?
fdoray
2016/06/15 17:14:32
No (constexpr + POD)
| |
| 42 constexpr ThreadPoolSettings kBackgroundFileIOPoolSettings{"BackgroundFileIO", | |
| 43 3, 3, 0}; | |
| 44 constexpr ThreadPoolSettings kForegroundPoolSettings{"Foreground", 4, 16, 100}; | |
| 45 constexpr ThreadPoolSettings kForegroundFileIOPoolSettings{"ForegroundFileIO", | |
| 46 8, 32, 200}; | |
| 47 | |
| 48 // Returns the integer associated with |key| in |map| or |default_value| there | |
| 49 // is no such integer. | |
| 50 int ReadIntegerFromMap(const std::string& key, | |
| 51 int default_value, | |
| 52 const std::map<std::string, std::string>& map) { | |
|
robliao
2016/06/14 21:43:44
Consider having the map argument first. This would
fdoray
2016/06/15 17:14:32
Done.
| |
| 53 auto it = map.find(key); | |
| 54 int value = 0; | |
| 55 if (it == map.end() || !StringToInt(it->second, &value)) | |
| 56 return default_value; | |
| 57 return value; | |
| 58 } | |
| 59 | |
| 60 int GetMaxThreadsForPool( | |
| 61 const ThreadPoolSettings& settings, | |
| 62 const std::map<std::string, std::string>& variation_params) { | |
| 63 DCHECK_GT(settings.default_min_threads, 0); | |
| 64 const std::string pool_name(settings.name); | |
| 65 const int min_threads = ReadIntegerFromMap( | |
| 66 pool_name + "MinThreads", settings.default_min_threads, variation_params); | |
| 67 DCHECK_GT(min_threads, 0); | |
| 68 const int max_threads = ReadIntegerFromMap( | |
| 69 pool_name + "MaxThreads", settings.default_max_threads, variation_params); | |
| 70 const int threads_percentage_num_processors = ReadIntegerFromMap( | |
| 71 pool_name + "ThreadsPercentageNumProcessors", | |
| 72 settings.default_threads_percentage_num_processors, variation_params); | |
| 73 | |
| 74 return std::max( | |
| 75 min_threads, | |
| 76 std::min(max_threads, threads_percentage_num_processors * | |
| 77 SysInfo::NumberOfProcessors() / 100)); | |
| 78 } | |
| 79 | |
| 80 } // namespace | |
| 81 | |
| 21 // static | 82 // static |
| 22 std::unique_ptr<TaskSchedulerImpl> TaskSchedulerImpl::Create() { | 83 std::unique_ptr<TaskSchedulerImpl> TaskSchedulerImpl::Create( |
| 84 const std::map<std::string, std::string>& variation_params) { | |
| 23 std::unique_ptr<TaskSchedulerImpl> scheduler(new TaskSchedulerImpl); | 85 std::unique_ptr<TaskSchedulerImpl> scheduler(new TaskSchedulerImpl); |
| 24 scheduler->Initialize(); | 86 scheduler->Initialize(variation_params); |
| 25 return scheduler; | 87 return scheduler; |
| 26 } | 88 } |
| 27 | 89 |
| 28 TaskSchedulerImpl::~TaskSchedulerImpl() { | 90 TaskSchedulerImpl::~TaskSchedulerImpl() { |
| 29 #if DCHECK_IS_ON() | 91 #if DCHECK_IS_ON() |
| 30 DCHECK(join_for_testing_returned_.IsSignaled()); | 92 DCHECK(join_for_testing_returned_.IsSignaled()); |
| 31 #endif | 93 #endif |
| 32 } | 94 } |
| 33 | 95 |
| 34 void TaskSchedulerImpl::PostTaskWithTraits( | 96 void TaskSchedulerImpl::PostTaskWithTraits( |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 : delayed_task_manager_( | 133 : delayed_task_manager_( |
| 72 Bind(&TaskSchedulerImpl::OnDelayedRunTimeUpdated, Unretained(this))) | 134 Bind(&TaskSchedulerImpl::OnDelayedRunTimeUpdated, Unretained(this))) |
| 73 #if DCHECK_IS_ON() | 135 #if DCHECK_IS_ON() |
| 74 , | 136 , |
| 75 join_for_testing_returned_(WaitableEvent::ResetPolicy::MANUAL, | 137 join_for_testing_returned_(WaitableEvent::ResetPolicy::MANUAL, |
| 76 WaitableEvent::InitialState::NOT_SIGNALED) | 138 WaitableEvent::InitialState::NOT_SIGNALED) |
| 77 #endif | 139 #endif |
| 78 { | 140 { |
| 79 } | 141 } |
| 80 | 142 |
| 81 void TaskSchedulerImpl::Initialize() { | 143 void TaskSchedulerImpl::Initialize( |
| 144 const std::map<std::string, std::string>& variation_params) { | |
| 82 using IORestriction = SchedulerThreadPoolImpl::IORestriction; | 145 using IORestriction = SchedulerThreadPoolImpl::IORestriction; |
| 83 | 146 |
| 147 const std::string thread_name_prefix(kTaskSchedulerThreadNamePrefix); | |
| 148 | |
| 84 const SchedulerThreadPoolImpl::ReEnqueueSequenceCallback | 149 const SchedulerThreadPoolImpl::ReEnqueueSequenceCallback |
| 85 re_enqueue_sequence_callback = | 150 re_enqueue_sequence_callback = |
| 86 Bind(&TaskSchedulerImpl::ReEnqueueSequenceCallback, Unretained(this)); | 151 Bind(&TaskSchedulerImpl::ReEnqueueSequenceCallback, Unretained(this)); |
| 87 | 152 |
| 88 // TODO(fdoray): Derive the number of threads per pool from hardware | |
| 89 // characteristics rather than using hard-coded constants. | |
| 90 | |
| 91 // Passing pointers to objects owned by |this| to | 153 // Passing pointers to objects owned by |this| to |
| 92 // SchedulerThreadPoolImpl::Create() is safe because a TaskSchedulerImpl can't | 154 // SchedulerThreadPoolImpl::Create() is safe because a TaskSchedulerImpl can't |
| 93 // be deleted before all its thread pools have been joined. | 155 // be deleted before all its thread pools have been joined. |
| 94 background_thread_pool_ = SchedulerThreadPoolImpl::Create( | 156 background_thread_pool_ = SchedulerThreadPoolImpl::Create( |
| 95 "TaskSchedulerBackground", ThreadPriority::BACKGROUND, 1U, | 157 thread_name_prefix + kBackgroundPoolSettings.name, |
| 158 ThreadPriority::BACKGROUND, | |
| 159 GetMaxThreadsForPool(kBackgroundPoolSettings, variation_params), | |
| 96 IORestriction::DISALLOWED, re_enqueue_sequence_callback, &task_tracker_, | 160 IORestriction::DISALLOWED, re_enqueue_sequence_callback, &task_tracker_, |
| 97 &delayed_task_manager_); | 161 &delayed_task_manager_); |
| 98 CHECK(background_thread_pool_); | 162 CHECK(background_thread_pool_); |
| 99 | 163 |
| 100 background_file_io_thread_pool_ = SchedulerThreadPoolImpl::Create( | 164 background_file_io_thread_pool_ = SchedulerThreadPoolImpl::Create( |
| 101 "TaskSchedulerBackgroundFileIO", ThreadPriority::BACKGROUND, 1U, | 165 thread_name_prefix + kBackgroundFileIOPoolSettings.name, |
| 166 ThreadPriority::BACKGROUND, | |
| 167 GetMaxThreadsForPool(kBackgroundFileIOPoolSettings, variation_params), | |
| 102 IORestriction::ALLOWED, re_enqueue_sequence_callback, &task_tracker_, | 168 IORestriction::ALLOWED, re_enqueue_sequence_callback, &task_tracker_, |
| 103 &delayed_task_manager_); | 169 &delayed_task_manager_); |
| 104 CHECK(background_file_io_thread_pool_); | 170 CHECK(background_file_io_thread_pool_); |
| 105 | 171 |
| 106 normal_thread_pool_ = SchedulerThreadPoolImpl::Create( | 172 normal_thread_pool_ = SchedulerThreadPoolImpl::Create( |
| 107 "TaskSchedulerForeground", ThreadPriority::NORMAL, 4U, | 173 thread_name_prefix + kForegroundPoolSettings.name, ThreadPriority::NORMAL, |
| 174 GetMaxThreadsForPool(kForegroundPoolSettings, variation_params), | |
| 108 IORestriction::DISALLOWED, re_enqueue_sequence_callback, &task_tracker_, | 175 IORestriction::DISALLOWED, re_enqueue_sequence_callback, &task_tracker_, |
| 109 &delayed_task_manager_); | 176 &delayed_task_manager_); |
| 110 CHECK(normal_thread_pool_); | 177 CHECK(normal_thread_pool_); |
| 111 | 178 |
| 112 normal_file_io_thread_pool_ = SchedulerThreadPoolImpl::Create( | 179 normal_file_io_thread_pool_ = SchedulerThreadPoolImpl::Create( |
| 113 "TaskSchedulerForegroundFileIO", ThreadPriority::NORMAL, 12U, | 180 thread_name_prefix + kForegroundFileIOPoolSettings.name, |
| 181 ThreadPriority::NORMAL, | |
| 182 GetMaxThreadsForPool(kForegroundFileIOPoolSettings, variation_params), | |
| 114 IORestriction::ALLOWED, re_enqueue_sequence_callback, &task_tracker_, | 183 IORestriction::ALLOWED, re_enqueue_sequence_callback, &task_tracker_, |
| 115 &delayed_task_manager_); | 184 &delayed_task_manager_); |
| 116 CHECK(normal_file_io_thread_pool_); | 185 CHECK(normal_file_io_thread_pool_); |
| 117 | 186 |
| 118 service_thread_ = SchedulerServiceThread::Create(&task_tracker_, | 187 service_thread_ = SchedulerServiceThread::Create(&task_tracker_, |
| 119 &delayed_task_manager_); | 188 &delayed_task_manager_); |
| 120 CHECK(service_thread_); | 189 CHECK(service_thread_); |
| 121 } | 190 } |
| 122 | 191 |
| 123 SchedulerThreadPool* TaskSchedulerImpl::GetThreadPoolForTraits( | 192 SchedulerThreadPool* TaskSchedulerImpl::GetThreadPoolForTraits( |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 148 GetThreadPoolForTraits(traits)->ReEnqueueSequence(std::move(sequence), | 217 GetThreadPoolForTraits(traits)->ReEnqueueSequence(std::move(sequence), |
| 149 sort_key); | 218 sort_key); |
| 150 } | 219 } |
| 151 | 220 |
| 152 void TaskSchedulerImpl::OnDelayedRunTimeUpdated() { | 221 void TaskSchedulerImpl::OnDelayedRunTimeUpdated() { |
| 153 service_thread_->WakeUp(); | 222 service_thread_->WakeUp(); |
| 154 } | 223 } |
| 155 | 224 |
| 156 } // namespace internal | 225 } // namespace internal |
| 157 } // namespace base | 226 } // namespace base |
| OLD | NEW |