910e62b5创建于 1月15日历史提交
// Copyright 2020 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_PLATFORM_CONFIGURATION_H_
#define CHROME_COMMON_PROFILER_THREAD_PROFILER_PLATFORM_CONFIGURATION_H_

#include <memory>
#include <optional>

#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "components/sampling_profiler/process_type.h"
#include "components/version_info/channel.h"

// If enabled, ThreadProfilerPlatformConfiguration::IsEnabledForThread() will
// return true for ThreadPoolWorker threads. This can use a normal feature
// config instead of being part of the RelativePopulations experiment group
// because the feature is only checked after the ThreadPool is created, at which
// point field trials have been set up.
BASE_DECLARE_FEATURE(kSamplingProfilerOnWorkerThreads);

// Encapsulates the platform-specific configuration for the ThreadProfiler.
//
// The interface functions this class make a distinction between 'supported' and
// 'enabled' state. Supported means the profiler can be run in *some*
// circumstances for *some* fraction of the population on the platform/{released
// Chrome channel, development/CQ build} combination. This state is intended to
// enable experiment reporting. This avoids spamming UMA with experiment state
// on platforms/channels where the profiler is not being run.
//
// Enabled means we chose to the run the profiler on at least some threads on a
// platform/{released Chrome channel, development/CQ build} combination that is
// configured for profiling. The overall enable/disable state should be reported
// to UMA in this case.
//
// The std::optional<version_info::Channel> release_channel passed to functions
// in this interface should be the channel for released Chrome and nullopt for
// development/CQ builds.
class ThreadProfilerPlatformConfiguration {
 public:
  // The relative populations to use for enabling/disabling the profiler.
  // |disabled| + |enabled| + |experiment| is expected to equal 100.
  // - Within the enabled population, profiling is always enabled.
  // - Within the disabled population, profiling is always disabled.
  // - The experiment population is further split down to N equal-sized
  // subgroups with different configurations.
  struct RelativePopulations {
    double disabled;
    double enabled;
    double experiment;
  };

  virtual ~ThreadProfilerPlatformConfiguration() = default;

  // Create the platform configuration.
  static std::unique_ptr<ThreadProfilerPlatformConfiguration> Create(
      bool browser_test_mode_enabled,
      base::RepeatingCallback<bool(double)> is_enabled_on_dev_callback =
          base::BindRepeating(IsEnabled));

  // True if the platform supports the StackSamplingProfiler and the profiler is
  // to be run for the released Chrome channel or development/CQ build.
  bool IsSupported(std::optional<version_info::Channel> release_channel) const;

  // Returns the relative population disposition for the released Chrome channel
  // or development/CQ build on the platform. See the documentation on
  // RelativePopulations. Enable rates are valid only if IsSupported().
  virtual RelativePopulations GetEnableRates(
      std::optional<version_info::Channel> release_channel) const = 0;

  // Returns the fraction of the time that profiling should be randomly enabled
  // for the child |process|. The return value is in the range [0.0, 1.0].
  virtual double GetChildProcessPerExecutionEnableFraction(
      sampling_profiler::ProfilerProcessType process) const = 0;

  // Choose a process to run profiling when profiling is enabled. Running
  // the sampler on a single process instead of all processes at the same time
  // will help reduce the impact on users. If std::nullopt is returned, the
  // setting can be ignored. All processes will be sampled.
  virtual std::optional<sampling_profiler::ProfilerProcessType>
  ChooseEnabledProcess() const = 0;

  // Returns whether the profiler is enabled for |thread| in |process|.
  virtual bool IsEnabledForThread(
      sampling_profiler::ProfilerProcessType process,
      sampling_profiler::ProfilerThreadType thread,
      std::optional<version_info::Channel> release_channel) const = 0;

 protected:
  // True if the profiler is to be run for the released Chrome channel or
  // development/CQ build on the platform. Does not need to check whether the
  // StackSamplingProfiler is supported on the platform since that's done in
  // IsSupported().
  virtual bool IsSupportedForChannel(
      std::optional<version_info::Channel> release_channel) const = 0;

 private:
  // Returns `true` with given `enabled_probability`, where
  // 0 <= `enabled_probability` <= 1.
  static bool IsEnabled(double enabled_probability);
};

#endif  // CHROME_COMMON_PROFILER_THREAD_PROFILER_PLATFORM_CONFIGURATION_H_