blob: 2128a2923cb0d432536737a3e4dc49b695dd1070 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_PROFILER_THREAD_PROFILER_CONFIGURATION_H_
#define CHROME_COMMON_PROFILER_THREAD_PROFILER_CONFIGURATION_H_
#include <optional>
#include <string>
#include <variant>
#include "base/containers/span.h"
#include "base/no_destructor.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "components/sampling_profiler/process_type.h"
namespace base {
class CommandLine;
} // namespace base
class ThreadProfilerPlatformConfiguration;
// ThreadProfilerConfiguration chooses a configuration for the enable state of
// the stack sampling profiler across all processes. This configuration is
// determined once at browser process startup. Configurations for child
// processes are communicated via command line arguments.
class ThreadProfilerConfiguration {
public:
// Returns the ThreadProfilerConfiguration for the process.
static ThreadProfilerConfiguration* Get();
~ThreadProfilerConfiguration() = delete;
ThreadProfilerConfiguration(const ThreadProfilerConfiguration&) = delete;
ThreadProfilerConfiguration& operator=(const ThreadProfilerConfiguration&) =
delete;
// Get the stack sampling params to use.
base::StackSamplingProfiler::SamplingParams GetSamplingParams() const;
// True if the profiler is enabled for any thread in the current process.
bool IsProfilerEnabledForCurrentProcess() const;
// True if the profiler should be started for |thread| in the current process.
bool IsProfilerEnabledForCurrentProcessAndThread(
sampling_profiler::ProfilerThreadType thread) const;
// Get the synthetic field trial configuration. Returns true if a synthetic
// field trial should be registered. This should only be called from the
// browser process. When run at startup, the profiler must use a synthetic
// field trial since it runs before the metrics field trials are initialized.
bool GetSyntheticFieldTrial(std::string* trial_name,
std::string* group_name) const;
// True if profiler should be enabled for the child process.
bool IsProfilerEnabledForChildProcess(
sampling_profiler::ProfilerProcessType child_process) const;
// Add a command line switch that instructs the child process to run the
// profiler. This should only be called from the browser process.
void AppendCommandLineSwitchForChildProcess(
base::CommandLine* command_line) const;
// The variation groups that represent the Chrome-wide profiling
// configurations. Exposed for testing.
enum VariationGroup {
// Disabled within the experiment.
kProfileDisabled,
// Disabled because the required module is not installed, and outside the
// experiment.
kProfileDisabledModuleNotInstalled,
// Enabled within the experiment (and paired with equal-sized
// kProfileDisabled group).
kProfileControl,
// Enabled outside of the experiment.
kProfileEnabled,
// Disabled outside of the experiment.
kProfileDisabledOutsideOfExperiment,
};
// Configuration variations, along with weights to use when randomly choosing
// one of a set of variations. Exposed for testing.
struct Variation {
VariationGroup group;
double weight;
};
// Randomly chooses a variation from the weighted variations. Weights are
// expected to sum to 100 as a sanity check. Exposed for testing.
// randValue is a random value in the interval [0, 1) and is used to
// determine the variation group.
static VariationGroup ChooseVariationGroup(
base::span<const Variation> variations,
double randValue);
private:
friend base::NoDestructor<ThreadProfilerConfiguration>;
struct BrowserProcessConfiguration {
// The configuration state for the browser process. If !has_value()
// profiling is disabled and no variations state is reported. Otherwise
// profiling is enabled based on the VariationGroup and the variation state
// is reported.
std::optional<VariationGroup> variation_group;
// In pick-single-type-of-process-to-sample mode, only a single process
// type will be profiled when profiling is enabled. If !has_value(), the
// profiling will be enabled for as many processes as possible.
std::optional<sampling_profiler::ProfilerProcessType>
process_type_to_sample;
};
// The configuration state in child processes.
enum ChildProcessConfiguration {
kChildProcessProfileDisabled,
kChildProcessProfileEnabled,
};
// The configuration state for the current process, browser or child.
using Configuration =
std::variant<BrowserProcessConfiguration, ChildProcessConfiguration>;
ThreadProfilerConfiguration();
// True if the profiler is to be enabled for |variation_group|.
static bool EnableForVariationGroup(
std::optional<VariationGroup> variation_group);
// True if the given process is picked to enable profiling. In pick-single-
// type-of-process-to-sample mode, only one type of process is picked to
// have profiling enabled so that the user impact can be minimized.
static bool IsProcessGloballyEnabled(
const ThreadProfilerConfiguration::BrowserProcessConfiguration& config,
sampling_profiler::ProfilerProcessType process);
// Generates a configuration for the browser process.
static BrowserProcessConfiguration GenerateBrowserProcessConfiguration(
const ThreadProfilerPlatformConfiguration& platform_configuration);
// Generates a configuration for a child process.
static ChildProcessConfiguration GenerateChildProcessConfiguration(
const base::CommandLine& command_line);
// Generates a configuration for the current process.
static Configuration GenerateConfiguration(
sampling_profiler::ProfilerProcessType process,
const ThreadProfilerPlatformConfiguration& platform_configuration);
// NOTE: all state in this class must be const and initialized at construction
// time to ensure thread-safe access post-construction.
// Platform-dependent configuration upon which |configuration_| is based.
const std::unique_ptr<ThreadProfilerPlatformConfiguration>
platform_configuration_;
// Represents the configuration to use in the current process.
const Configuration configuration_;
};
#endif // CHROME_COMMON_PROFILER_THREAD_PROFILER_CONFIGURATION_H_