Chromium Code Reviews| Index: chrome/browser/chrome_browser_main.cc |
| diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc |
| index d1a7a6e3866a7442a68adb0d2c8ef6b4d0b92f2d..078bc919fcc9ff7b1bc341e890035a22ad7bf299 100644 |
| --- a/chrome/browser/chrome_browser_main.cc |
| +++ b/chrome/browser/chrome_browser_main.cc |
| @@ -7,6 +7,8 @@ |
| #include <stddef.h> |
| #include <stdint.h> |
| +#include <algorithm> |
| +#include <map> |
| #include <set> |
| #include <string> |
| #include <utility> |
| @@ -33,6 +35,9 @@ |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/sys_info.h" |
| +#include "base/task_scheduler/scheduler_worker_pool_params.h" |
| +#include "base/task_scheduler/task_scheduler.h" |
| +#include "base/task_scheduler/task_traits.h" |
| #include "base/threading/platform_thread.h" |
| #include "base/time/default_tick_clock.h" |
| #include "base/time/time.h" |
| @@ -317,6 +322,158 @@ void AddFirstRunNewTabs(StartupBrowserCreator* browser_creator, |
| } |
| #endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS) |
| +enum WorkerPoolType : size_t { |
|
fdoray
2016/08/05 20:58:54
enum class?
robliao
2016/08/05 22:23:28
I kept this as an enum for the similar reason we d
|
| + BACKGROUND_WORKER_POOL = 0, |
| + BACKGROUND_FILE_IO_WORKER_POOL, |
| + FOREGROUND_WORKER_POOL, |
| + FOREGROUND_FILE_IO_WORKER_POOL, |
| + WORKER_POOL_COUNT, |
| +}; |
| + |
| +struct WorkerPoolVariationValues { |
| + WorkerPoolVariationValues() |
| + : threads(0), |
| + detach_milliseconds(0) {} |
| + |
| + int threads; |
|
fdoray
2016/08/05 20:58:53
struct WorkerPoolVariationValues {
int threads =
robliao
2016/08/05 22:23:28
Done. I kept forgetting about inline initializatio
|
| + int64_t detach_milliseconds; |
| +}; |
| + |
| +// Converts |pool_descriptor| to a WorkerPoolVariationValues. Returns a default |
|
fdoray
2016/08/05 20:58:53
|pool_descriptor| is a string that follows the for
robliao
2016/08/05 22:23:29
Done.
|
| +// WorkerPoolVariationValues on failure. |
|
fdoray
2016/08/05 20:58:54
No need to document what the function does after N
robliao
2016/08/05 22:23:28
See below on the NOTREACHED discussion. Changed to
|
| +WorkerPoolVariationValues StringToWorkerPoolVariationValues( |
| + const base::StringPiece& pool_descriptor) { |
| + std::vector<std::string> tokens = SplitString(pool_descriptor, ",", |
|
fdoray
2016/08/05 20:58:53
const
robliao
2016/08/05 22:23:29
Done.
|
| + base::KEEP_WHITESPACE, |
| + base::SPLIT_WANT_NONEMPTY); |
| + int minimum; |
| + int maximum; |
| + double multiplier; |
| + int offset; |
| + int detach_milliseconds; |
| + // Checking for a size greater than the expected amount allows us to be |
| + // forward compatible if we add more variation values. |
| + if (tokens.size() >= 5 && |
| + base::StringToInt(tokens[0], &minimum) && |
| + base::StringToInt(tokens[1], &maximum) && |
| + base::StringToDouble(tokens[2], &multiplier) && |
| + base::StringToInt(tokens[3], &offset) && |
| + base::StringToInt(tokens[4], &detach_milliseconds)) { |
| + int num_of_cores = base::SysInfo::NumberOfProcessors(); |
| + int threads = std::round<int>(num_of_cores * multiplier) + offset; |
|
fdoray
2016/08/05 20:58:54
const num_of_cores
const threads
robliao
2016/08/05 22:23:28
Done.
|
| + WorkerPoolVariationValues values; |
| + values.threads = std::min(maximum, std::max(minimum, threads)); |
| + values.detach_milliseconds = detach_milliseconds; |
| + return values; |
| + } |
| + NOTREACHED() << "Invalid Worker Pool Descriptor: " << pool_descriptor; |
| + return WorkerPoolVariationValues(); |
| +} |
| + |
| +// Returns the worker pool index for |traits| defaulting to |
| +// FOREGROUND_WORKER_POOL or FOREGROUND_FILE_IO_WORKER_POOL on unknown |
| +// priorities. |
| +size_t WorkerPoolIndexForTraits(const base::TaskTraits& traits) { |
| + if (traits.with_file_io()) { |
| + return traits.priority() == base::TaskPriority::BACKGROUND |
| + ? WorkerPoolType::BACKGROUND_FILE_IO_WORKER_POOL |
| + : WorkerPoolType::FOREGROUND_FILE_IO_WORKER_POOL; |
| + } |
| + return traits.priority() == base::TaskPriority::BACKGROUND |
| + ? WorkerPoolType::BACKGROUND_WORKER_POOL |
| + : WorkerPoolType::FOREGROUND_WORKER_POOL; |
| +} |
| + |
| +// Initializes the Default Browser Task Scheduler if there is a valid variation |
| +// parameter for the field trial. |
| +void MaybeInitializeTaskScheduler() { |
| + static const char kFieldTrialName[] = "BrowserScheduler"; |
|
fdoray
2016/08/05 20:58:54
constexpr
robliao
2016/08/05 22:23:29
Done.
|
| + std::map<std::string, std::string> variation_params; |
| + if (!variations::GetVariationParams(kFieldTrialName, &variation_params)) |
| + return; |
| + |
| + // Order matches WorkerPoolType above. |
| + static const char* kWorkerPoolNames[] = { |
|
fdoray
2016/08/05 20:58:54
constexpr
robliao
2016/08/05 22:23:29
This triggers a compiler bug, so it's going to hav
|
| + "Background", |
| + "BackgroundFileIO", |
| + "Foreground", |
| + "ForegroundFileIO", |
| + }; |
| + static_assert( |
| + arraysize(kWorkerPoolNames) == WorkerPoolType::WORKER_POOL_COUNT, |
| + "Mismatched Worker Pool Types and Names"); |
| + |
| + std::vector<WorkerPoolVariationValues> values; |
| + for (size_t i = 0; i < arraysize(kWorkerPoolNames); i++) { |
| + const char* current = kWorkerPoolNames[i]; |
| + auto pair = variation_params.find(current); |
| + if (pair == variation_params.end()) { |
| + NOTREACHED() << "Missing Worker Pool Configuration: " << current; |
|
fdoray
2016/08/05 20:58:54
https://chromium.googlesource.com/chromium/src/+/m
robliao
2016/08/05 22:23:29
I guess these are coming in from the land of netwo
|
| + return; |
| + } |
| + |
| + const WorkerPoolVariationValues variation_value = |
| + StringToWorkerPoolVariationValues(pair->second); |
| + |
| + if (variation_value.threads == 0 || |
| + variation_value.detach_milliseconds == 0) { |
| + NOTREACHED() << "Invalid Worker Pool Configuration: " << current << |
| + " [" << pair->second << "]"; |
|
fdoray
2016/08/05 20:58:53
ditto
robliao
2016/08/05 22:23:28
See above.
|
| + return; |
| + } |
| + |
| + values.push_back(variation_value); |
| + } |
| + |
| + DCHECK_EQ(values.size(), WorkerPoolType::WORKER_POOL_COUNT); |
|
fdoray
2016/08/05 20:58:54
overkill DCHECK?
I don't suggest that you remove i
robliao
2016/08/05 22:23:29
I guess it's not intrinsic that the values.size()
|
| + |
| + using ThreadPriority = base::ThreadPriority; |
| + using IORestriction = base::SchedulerWorkerPoolParams::IORestriction; |
| + std::vector<base::SchedulerWorkerPoolParams> params_vector; |
| + DCHECK_EQ(params_vector.size(), WorkerPoolType::BACKGROUND_WORKER_POOL); |
| + params_vector.emplace_back( |
| + kWorkerPoolNames[BACKGROUND_WORKER_POOL], |
| + ThreadPriority::BACKGROUND, |
| + IORestriction::DISALLOWED, |
| + values[BACKGROUND_WORKER_POOL].threads, |
| + base::TimeDelta::FromMilliseconds( |
| + values[BACKGROUND_WORKER_POOL].detach_milliseconds)); |
| + |
| + DCHECK_EQ(params_vector.size(), |
| + WorkerPoolType::BACKGROUND_FILE_IO_WORKER_POOL); |
| + params_vector.emplace_back( |
| + kWorkerPoolNames[BACKGROUND_FILE_IO_WORKER_POOL], |
| + ThreadPriority::BACKGROUND, |
| + IORestriction::ALLOWED, |
| + values[BACKGROUND_FILE_IO_WORKER_POOL].threads, |
| + base::TimeDelta::FromMilliseconds( |
| + values[BACKGROUND_FILE_IO_WORKER_POOL].detach_milliseconds)); |
| + |
| + DCHECK_EQ(params_vector.size(), WorkerPoolType::FOREGROUND_WORKER_POOL); |
| + params_vector.emplace_back( |
| + kWorkerPoolNames[FOREGROUND_WORKER_POOL], |
| + ThreadPriority::NORMAL, |
| + IORestriction::DISALLOWED, |
| + values[FOREGROUND_WORKER_POOL].threads, |
| + base::TimeDelta::FromMilliseconds( |
| + values[FOREGROUND_WORKER_POOL].detach_milliseconds)); |
| + |
| + DCHECK_EQ(params_vector.size(), |
| + WorkerPoolType::FOREGROUND_FILE_IO_WORKER_POOL); |
| + params_vector.emplace_back( |
| + kWorkerPoolNames[FOREGROUND_FILE_IO_WORKER_POOL], |
| + ThreadPriority::NORMAL, |
| + IORestriction::ALLOWED, |
| + values[FOREGROUND_FILE_IO_WORKER_POOL].threads, |
| + base::TimeDelta::FromMilliseconds( |
| + values[FOREGROUND_FILE_IO_WORKER_POOL].detach_milliseconds)); |
| + |
| + DCHECK_EQ(params_vector.size(), WorkerPoolType::WORKER_POOL_COUNT); |
| + |
| + base::TaskScheduler::CreateAndSetDefaultTaskScheduler( |
| + params_vector, base::Bind(WorkerPoolIndexForTraits)); |
| +} |
| + |
| // Returns the new local state object, guaranteed non-NULL. |
| // |local_state_task_runner| must be a shutdown-blocking task runner. |
| PrefService* InitializeLocalState( |
| @@ -1214,6 +1371,8 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() { |
| // IOThread's initialization which happens in BrowserProcess:PreCreateThreads. |
| SetupMetricsAndFieldTrials(); |
| + MaybeInitializeTaskScheduler(); |
| + |
| // ChromeOS needs ResourceBundle::InitSharedInstance to be called before this. |
| browser_process_->PreCreateThreads(); |