| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/task_scheduler_util/variations_util.h" |
| |
| #include <map> |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/metrics/field_trial_params.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| #include "base/task_scheduler/initialization_util.h" |
| #include "base/time/time.h" |
| |
| namespace task_scheduler_util { |
| |
| namespace { |
| |
| // Builds a SchedulerWorkerPoolParams from the pool descriptor in |
| // |variation_params[variation_param_prefix + pool_name]|. Returns an invalid |
| // SchedulerWorkerPoolParams on failure. |
| // |
| // The pool descriptor is a semi-colon separated value string with the following |
| // items: |
| // 0. Minimum Thread Count (int) |
| // 1. Maximum Thread Count (int) |
| // 2. Thread Count Multiplier (double) |
| // 3. Thread Count Offset (int) |
| // 4. Detach Time in Milliseconds (int) |
| // Additional values may appear as necessary and will be ignored. |
| std::unique_ptr<base::SchedulerWorkerPoolParams> GetWorkerPoolParams( |
| base::StringPiece variation_param_prefix, |
| base::StringPiece pool_name, |
| const std::map<std::string, std::string>& variation_params) { |
| auto pool_descriptor_it = |
| variation_params.find(base::StrCat({variation_param_prefix, pool_name})); |
| if (pool_descriptor_it == variation_params.end()) |
| return nullptr; |
| const auto& pool_descriptor = pool_descriptor_it->second; |
| |
| const std::vector<base::StringPiece> tokens = SplitStringPiece( |
| pool_descriptor, ";", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| // Normally, we wouldn't initialize the values below because we don't read |
| // from them before we write to them. However, some compilers (like MSVC) |
| // complain about uninitialized variables due to the as_string() call below. |
| int min = 0; |
| int max = 0; |
| double cores_multiplier = 0.0; |
| int offset = 0; |
| int detach_milliseconds = 0; |
| // 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], &min) || |
| !base::StringToInt(tokens[1], &max) || |
| !base::StringToDouble(tokens[2].as_string(), &cores_multiplier) || |
| !base::StringToInt(tokens[3], &offset) || |
| !base::StringToInt(tokens[4], &detach_milliseconds)) { |
| DLOG(ERROR) << "Invalid Worker Pool Descriptor Format: " << pool_descriptor; |
| return nullptr; |
| } |
| |
| auto params = std::make_unique<base::SchedulerWorkerPoolParams>( |
| base::RecommendedMaxNumberOfThreadsInPool(min, max, cores_multiplier, |
| offset), |
| base::TimeDelta::FromMilliseconds(detach_milliseconds)); |
| |
| if (params->max_tasks() <= 0) { |
| DLOG(ERROR) << "Invalid max tasks in the Worker Pool Descriptor: " |
| << params->max_tasks(); |
| return nullptr; |
| } |
| |
| if (params->suggested_reclaim_time() < base::TimeDelta()) { |
| DLOG(ERROR) |
| << "Invalid suggested reclaim time in the Worker Pool Descriptor:" |
| << params->suggested_reclaim_time(); |
| return nullptr; |
| } |
| |
| return params; |
| } |
| |
| } // namespace |
| |
| std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams( |
| base::StringPiece variation_param_prefix) { |
| std::map<std::string, std::string> variation_params; |
| if (!base::GetFieldTrialParams("BrowserScheduler", &variation_params)) |
| return nullptr; |
| |
| const auto background_worker_pool_params = GetWorkerPoolParams( |
| variation_param_prefix, "Background", variation_params); |
| const auto background_blocking_worker_pool_params = GetWorkerPoolParams( |
| variation_param_prefix, "BackgroundBlocking", variation_params); |
| const auto foreground_worker_pool_params = GetWorkerPoolParams( |
| variation_param_prefix, "Foreground", variation_params); |
| const auto foreground_blocking_worker_pool_params = GetWorkerPoolParams( |
| variation_param_prefix, "ForegroundBlocking", variation_params); |
| |
| if (!background_worker_pool_params || |
| !background_blocking_worker_pool_params || |
| !foreground_worker_pool_params || |
| !foreground_blocking_worker_pool_params) { |
| return nullptr; |
| } |
| |
| return std::make_unique<base::TaskScheduler::InitParams>( |
| *background_worker_pool_params, *background_blocking_worker_pool_params, |
| *foreground_worker_pool_params, *foreground_blocking_worker_pool_params); |
| } |
| |
| std::unique_ptr<base::TaskScheduler::InitParams> |
| GetTaskSchedulerInitParamsForBrowser() { |
| // Variations params for the browser processes have no prefix. |
| constexpr char kVariationParamPrefix[] = ""; |
| return GetTaskSchedulerInitParams(kVariationParamPrefix); |
| } |
| |
| std::unique_ptr<base::TaskScheduler::InitParams> |
| GetTaskSchedulerInitParamsForRenderer() { |
| // Variations params for renderer processes are prefixed with "Renderer". |
| constexpr char kVariationParamPrefix[] = "Renderer"; |
| return GetTaskSchedulerInitParams(kVariationParamPrefix); |
| } |
| |
| } // namespace task_scheduler_util |