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..070d60e176a5a8b6fdbbc27d6cc050e1b5a579ef 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> |
@@ -21,6 +23,7 @@ |
#include "base/feature_list.h" |
#include "base/files/file_path.h" |
#include "base/files/file_util.h" |
+#include "base/logging.h" |
#include "base/memory/ptr_util.h" |
#include "base/metrics/field_trial.h" |
#include "base/metrics/histogram_macros.h" |
@@ -33,6 +36,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 +323,127 @@ void AddFirstRunNewTabs(StartupBrowserCreator* browser_creator, |
} |
#endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS) |
+enum WorkerPoolType : size_t { |
+ BACKGROUND_WORKER_POOL = 0, |
+ BACKGROUND_FILE_IO_WORKER_POOL, |
+ FOREGROUND_WORKER_POOL, |
+ FOREGROUND_FILE_IO_WORKER_POOL, |
+ WORKER_POOL_COUNT // Always last. |
+}; |
+ |
+struct WorkerPoolVariationValues { |
+ int threads = 0; |
+ base::TimeDelta detach_period; |
+}; |
+ |
+// Converts |pool_descriptor| to a WorkerPoolVariationValues. Returns a default |
+// WorkerPoolVariationValues on failure. |
+// |
+// |pool_descriptor| is a comma separated value string with the following items: |
+// 1. Minimum Thread Count (int) |
+// 2. Maximum Thread Count (int) |
+// 3. Thread Count Multiplier (double) |
+// 4. Thread Count Offset (int) |
+// 5. Detach Time in Milliseconds (milliseconds) |
+// Additional values may appear as necessary and will be ignored. |
+WorkerPoolVariationValues StringToWorkerPoolVariationValues( |
+ const base::StringPiece pool_descriptor) { |
+ const std::vector<std::string> tokens = |
+ SplitString(pool_descriptor, ",", |
+ 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)) { |
+ const int num_of_cores = base::SysInfo::NumberOfProcessors(); |
+ const int threads = std::ceil<int>(num_of_cores * multiplier) + offset; |
+ WorkerPoolVariationValues values; |
+ values.threads = std::min(maximum, std::max(minimum, threads)); |
+ values.detach_period = |
+ base::TimeDelta::FromMilliseconds(detach_milliseconds); |
+ return values; |
+ } |
+ DLOG(ERROR) << "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) { |
+ bool is_background = traits.priority() == base::TaskPriority::BACKGROUND; |
gab
2016/08/09 15:54:56
const ?
robliao
2016/08/09 19:14:37
Done.
|
+ if (traits.with_file_io()) { |
+ return is_background ? BACKGROUND_FILE_IO_WORKER_POOL |
+ : FOREGROUND_FILE_IO_WORKER_POOL; |
+ } |
+ return is_background ? BACKGROUND_WORKER_POOL : FOREGROUND_WORKER_POOL; |
+} |
+ |
+// Initializes the Default Browser Task Scheduler if there is a valid variation |
+// parameter for the field trial. |
+void MaybeInitializeTaskScheduler() { |
+ static constexpr char kFieldTrialName[] = "BrowserScheduler"; |
+ std::map<std::string, std::string> variation_params; |
+ if (!variations::GetVariationParams(kFieldTrialName, &variation_params)) |
+ return; |
+ |
+ using ThreadPriority = base::ThreadPriority; |
+ using IORestriction = base::SchedulerWorkerPoolParams::IORestriction; |
+ struct SchedulerWorkerPoolPredefinedParams { |
+ const char* name; |
+ ThreadPriority priority_hint; |
+ IORestriction io_restriction; |
+ }; |
+ static const SchedulerWorkerPoolPredefinedParams kAllPredefinedParams[] = { |
+ {"Background", ThreadPriority::BACKGROUND, IORestriction::DISALLOWED}, |
+ {"BackgroundFileIO", ThreadPriority::BACKGROUND, IORestriction::ALLOWED}, |
+ {"Foreground", ThreadPriority::NORMAL, IORestriction::DISALLOWED}, |
+ {"ForegroundFileIO", ThreadPriority::NORMAL, IORestriction::ALLOWED}, |
+ }; |
+ static_assert(arraysize(kAllPredefinedParams) == WORKER_POOL_COUNT, |
+ "Mismatched Worker Pool Types and Predefined Parameters"); |
+ |
+ std::vector<base::SchedulerWorkerPoolParams> params_vector; |
+ for (const auto& predefined_params : kAllPredefinedParams) { |
+ const auto pair = variation_params.find(predefined_params.name); |
+ if (pair == variation_params.end()) { |
+ DLOG(ERROR) << "Missing Worker Pool Configuration: " |
+ << predefined_params.name; |
+ return; |
+ } |
+ |
+ const WorkerPoolVariationValues variation_values = |
+ StringToWorkerPoolVariationValues(pair->second); |
+ |
+ if (variation_values.threads <= 0 || |
+ variation_values.detach_period.is_zero()) { |
+ DLOG(ERROR) << "Invalid Worker Pool Configuration: " << |
+ predefined_params.name << " [" << pair->second << "]"; |
+ return; |
+ } |
+ |
+ params_vector.emplace_back(predefined_params.name, |
+ predefined_params.priority_hint, |
+ predefined_params.io_restriction, |
+ variation_values.threads, |
+ variation_values.detach_period); |
+ } |
+ |
+ DCHECK_EQ(WORKER_POOL_COUNT, params_vector.size()); |
+ |
+ 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 +1341,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(); |