1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/heap_profiling/in_process/heap_profiler_parameters.h"
#include "base/check_op.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/sampling_profiler/process_type.h"
namespace heap_profiling {
namespace {
// Platform-specific parameter defaults.
#if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID)
// Default on iOS is equal to mean value of process uptime. Android is
// more similar to iOS than to Desktop.
constexpr base::TimeDelta kDefaultCollectionInterval = base::Minutes(30);
#else
// Default on desktop is once per day.
constexpr base::TimeDelta kDefaultCollectionInterval = base::Days(1);
#endif
// Average 10M bytes per sample.
constexpr int kDefaultSamplingRateBytes = 10'000'000;
// The chance that this client will report heap samples through a metrics
// provider if it's on the stable channel.
#if BUILDFLAG(IS_ANDROID)
// With stable-probability 0.01 we get about 4x as many records as before
// https://crrev.com/c/3309878 landed in 98.0.4742.0, even with ARM64
// disabled. This is too high a volume to process.
constexpr double kDefaultStableProbability = 0.0025;
#else
constexpr double kDefaultStableProbability = 0.01;
#endif
// The chance that this client will report heap samples through a metrics
// provider if it's on a non-stable channel.
constexpr double kDefaultNonStableProbability = 0.5;
// The probability of including a child process in each snapshot that's taken,
// as a percentage from 0 to 100. Defaults to 100, but can be set lower to
// sub-sample process types that are very common (mainly renderers) to keep data
// volume low. Samples from child processes are weighted in inverse proportion
// to the snapshot probability to normalize the aggregated results. Set to 0 to
// disable sampling a process completely.
constexpr base::FeatureParam<int> kGpuSnapshotProbability{
&kHeapProfilerReporting, "gpu-prob-pct", 100};
constexpr base::FeatureParam<int> kNetworkSnapshotProbability{
&kHeapProfilerReporting, "network-prob-pct", 100};
// Sample 10% of renderer processes by default, because last time this was
// evaluated (2024-08) the 50th %ile of renderer process count
// (Memory.RenderProcessHost.Count2.All) ranged from 8 on Windows to 18 on Mac.
// 10% is an easy default between 1/18 and 1/8.
constexpr base::FeatureParam<int> kRendererSnapshotProbability{
&kHeapProfilerReporting, "renderer-prob-pct",
#if BUILDFLAG(IS_CHROMEOS)
// base::debug::TraceStackFramePointers is crashing in ChromeOS rendererer
// processes. Disable heap profiling there for now.
// TODO(crbug.com/402542102): Find the root cause and re-enable.
0
#else
10
#endif
};
// Sample 50% of utility processes by default, because last time this was
// evaluated (2024-08) the profiler collected 1.8x as many snapshots on Mac and
// 2.4x as many snapshots on Windows for each browser process snapshot.
constexpr base::FeatureParam<int> kUtilitySnapshotProbability{
&kHeapProfilerReporting, "utility-prob-pct", 50};
// The sampling rates of each process type, in bytes.
constexpr base::FeatureParam<int> kBrowserSamplingRateBytes{
&kHeapProfilerReporting, "browser-sampling-rate-bytes",
kDefaultSamplingRateBytes};
// Use half the threshold used in the browser process, because last time it was
// validated the GPU process allocated a bit over half as much memory at the
// median.
constexpr base::FeatureParam<int> kGpuSamplingRateBytes{
&kHeapProfilerReporting, "gpu-sampling-rate-bytes",
kDefaultSamplingRateBytes / 2};
constexpr base::FeatureParam<int> kNetworkSamplingRateBytes{
&kHeapProfilerReporting, "network-sampling-rate-bytes",
kDefaultSamplingRateBytes};
constexpr base::FeatureParam<int> kRendererSamplingRateBytes{
&kHeapProfilerReporting, "renderer-sampling-rate-bytes",
kDefaultSamplingRateBytes};
// Use 1/10th the threshold used in the browser process, because last time it
// was validated with the default sampling rate (2024-08) the sampler collected
// 6% to 11% as many samples per snapshot in the utility process, depending on
// platform.
constexpr base::FeatureParam<int> kUtilitySamplingRateBytes{
&kHeapProfilerReporting, "utility-sampling-rate-bytes",
kDefaultSamplingRateBytes / 10};
// The load factor that should be used by PoissonAllocationSampler's hash set in
// each process type.
constexpr base::FeatureParam<double> kBrowserHashSetLoadFactor{
&kHeapProfilerReporting, "browser-hash-set-load-factor", 1.0};
constexpr base::FeatureParam<double> kGpuHashSetLoadFactor{
&kHeapProfilerReporting, "gpu-hash-set-load-factor", 1.0};
constexpr base::FeatureParam<double> kNetworkHashSetLoadFactor{
&kHeapProfilerReporting, "network-hash-set-load-factor", 1.0};
constexpr base::FeatureParam<double> kRendererHashSetLoadFactor{
&kHeapProfilerReporting, "renderer-hash-set-load-factor", 1.0};
constexpr base::FeatureParam<double> kUtilityHashSetLoadFactor{
&kHeapProfilerReporting, "utility-hash-set-load-factor", 1.0};
} // namespace
BASE_FEATURE(kHeapProfilerReporting,
"HeapProfilerReporting",
base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<double> kStableProbability{
&kHeapProfilerReporting, "stable-probability", kDefaultStableProbability};
const base::FeatureParam<double> kNonStableProbability{
&kHeapProfilerReporting, "nonstable-probability",
kDefaultNonStableProbability};
const base::FeatureParam<base::TimeDelta> kCollectionInterval{
&kHeapProfilerReporting, "collection-interval", kDefaultCollectionInterval};
size_t GetSamplingRateForProcess(
sampling_profiler::ProfilerProcessType process_type) {
int sampling_rate_bytes;
switch (process_type) {
case sampling_profiler::ProfilerProcessType::kBrowser:
sampling_rate_bytes = kBrowserSamplingRateBytes.Get();
break;
case sampling_profiler::ProfilerProcessType::kRenderer:
sampling_rate_bytes = kRendererSamplingRateBytes.Get();
break;
case sampling_profiler::ProfilerProcessType::kGpu:
sampling_rate_bytes = kGpuSamplingRateBytes.Get();
break;
case sampling_profiler::ProfilerProcessType::kUtility:
sampling_rate_bytes = kUtilitySamplingRateBytes.Get();
break;
case sampling_profiler::ProfilerProcessType::kNetworkService:
sampling_rate_bytes = kNetworkSamplingRateBytes.Get();
break;
case sampling_profiler::ProfilerProcessType::kUnknown:
default:
// Profiler should not be enabled for these process types.
NOTREACHED();
}
return base::saturated_cast<size_t>(sampling_rate_bytes);
}
int GetSnapshotProbabilityForProcess(
sampling_profiler::ProfilerProcessType process_type) {
int snapshot_probability_pct;
switch (process_type) {
case sampling_profiler::ProfilerProcessType::kBrowser:
// Should only be called for child processes.
NOTREACHED();
case sampling_profiler::ProfilerProcessType::kGpu:
snapshot_probability_pct = kGpuSnapshotProbability.Get();
break;
case sampling_profiler::ProfilerProcessType::kNetworkService:
snapshot_probability_pct = kNetworkSnapshotProbability.Get();
break;
case sampling_profiler::ProfilerProcessType::kRenderer:
snapshot_probability_pct = kRendererSnapshotProbability.Get();
break;
case sampling_profiler::ProfilerProcessType::kUtility:
snapshot_probability_pct = kUtilitySnapshotProbability.Get();
break;
default:
// Unsupported process type.
snapshot_probability_pct = 0;
break;
}
CHECK_GE(snapshot_probability_pct, 0);
CHECK_LE(snapshot_probability_pct, 100);
return snapshot_probability_pct;
}
float GetHashSetLoadFactorForProcess(
sampling_profiler::ProfilerProcessType process_type) {
switch (process_type) {
case sampling_profiler::ProfilerProcessType::kBrowser:
return kBrowserHashSetLoadFactor.Get();
case sampling_profiler::ProfilerProcessType::kGpu:
return kGpuHashSetLoadFactor.Get();
case sampling_profiler::ProfilerProcessType::kNetworkService:
return kNetworkHashSetLoadFactor.Get();
case sampling_profiler::ProfilerProcessType::kRenderer:
return kRendererHashSetLoadFactor.Get();
case sampling_profiler::ProfilerProcessType::kUtility:
return kUtilityHashSetLoadFactor.Get();
default:
NOTREACHED();
}
}
} // namespace heap_profiling
|