| // Copyright 2015 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 "chrome/browser/stack_sampling_configuration.h" |
| |
| #include "base/rand_util.h" |
| #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" |
| #include "chrome/common/channel_info.h" |
| #include "components/version_info/version_info.h" |
| |
| namespace { |
| |
| // The profiler is currently only implemented for Windows x64, and only runs on |
| // trunk, canary, and dev. |
| bool IsProfilerSupported() { |
| #if !defined(_WIN64) |
| return false; |
| #else |
| const version_info::Channel channel = chrome::GetChannel(); |
| return (channel == version_info::Channel::UNKNOWN || |
| channel == version_info::Channel::CANARY || |
| channel == version_info::Channel::DEV); |
| #endif |
| } |
| |
| } // namespace |
| |
| StackSamplingConfiguration::StackSamplingConfiguration() |
| : configuration_(GenerateConfiguration()) { |
| } |
| |
| base::StackSamplingProfiler::SamplingParams |
| StackSamplingConfiguration::GetSamplingParams() const { |
| base::StackSamplingProfiler::SamplingParams params; |
| params.bursts = 1; |
| const base::TimeDelta duration = base::TimeDelta::FromSeconds(30); |
| |
| switch (configuration_) { |
| case PROFILE_DISABLED: |
| case PROFILE_CONTROL: |
| params.initial_delay = base::TimeDelta::FromMilliseconds(0); |
| params.sampling_interval = base::TimeDelta::FromMilliseconds(0); |
| params.samples_per_burst = 0; |
| break; |
| |
| case PROFILE_NO_SAMPLES: |
| params.initial_delay = duration; |
| params.sampling_interval = base::TimeDelta::FromMilliseconds(0); |
| params.samples_per_burst = 0; |
| break; |
| |
| case PROFILE_5HZ: |
| params.initial_delay = base::TimeDelta::FromMilliseconds(0); |
| params.sampling_interval = base::TimeDelta::FromMilliseconds(200); |
| params.samples_per_burst = duration / params.sampling_interval; |
| break; |
| |
| case PROFILE_10HZ: |
| params.initial_delay = base::TimeDelta::FromMilliseconds(0); |
| params.sampling_interval = base::TimeDelta::FromMilliseconds(100); |
| params.samples_per_burst = duration / params.sampling_interval; |
| break; |
| |
| case PROFILE_100HZ: |
| params.initial_delay = base::TimeDelta::FromMilliseconds(0); |
| params.sampling_interval = base::TimeDelta::FromMilliseconds(10); |
| params.samples_per_burst = duration / params.sampling_interval; |
| break; |
| } |
| return params; |
| } |
| |
| bool StackSamplingConfiguration::IsProfilerEnabled() const { |
| return (configuration_ != PROFILE_DISABLED && |
| configuration_ != PROFILE_CONTROL); |
| } |
| |
| void StackSamplingConfiguration::RegisterSyntheticFieldTrial() const { |
| if (!IsProfilerSupported()) |
| return; |
| |
| std::string group; |
| switch (configuration_) { |
| case PROFILE_DISABLED: |
| group = "Disabled"; |
| break; |
| |
| case PROFILE_CONTROL: |
| group = "Control"; |
| break; |
| |
| case PROFILE_NO_SAMPLES: |
| group = "NoSamples"; |
| break; |
| |
| case PROFILE_5HZ: |
| group = "5Hz"; |
| break; |
| |
| case PROFILE_10HZ: |
| group = "10Hz"; |
| break; |
| |
| case PROFILE_100HZ: |
| group = "100Hz"; |
| break; |
| } |
| |
| ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( |
| "SyntheticStackProfilingConfiguration", |
| group); |
| } |
| |
| // static |
| StackSamplingConfiguration::ProfileConfiguration |
| StackSamplingConfiguration::GenerateConfiguration() { |
| if (!IsProfilerSupported()) |
| return PROFILE_DISABLED; |
| |
| // Enable the profiler in the intended ultimate production configuration for |
| // development/waterfall builds. |
| if (chrome::GetChannel() == version_info::Channel::UNKNOWN) |
| return PROFILE_10HZ; |
| |
| // Enable according to the variations below in canary and dev. |
| if (chrome::GetChannel() == version_info::Channel::CANARY || |
| chrome::GetChannel() == version_info::Channel::DEV) { |
| struct Variation { |
| ProfileConfiguration config; |
| int weight; |
| }; |
| |
| // Generate a configuration according to the associated weights. |
| const Variation variations[] = { |
| { PROFILE_10HZ, 100}, |
| { PROFILE_CONTROL, 0}, |
| { PROFILE_DISABLED, 0} |
| }; |
| |
| int total_weight = 0; |
| for (const Variation& variation : variations) |
| total_weight += variation.weight; |
| DCHECK_EQ(100, total_weight); |
| |
| int chosen = base::RandInt(0, total_weight - 1); // Max is inclusive. |
| int cumulative_weight = 0; |
| for (const Variation& variation : variations) { |
| if (chosen >= cumulative_weight && |
| chosen < cumulative_weight + variation.weight) { |
| return variation.config; |
| } |
| cumulative_weight += variation.weight; |
| } |
| NOTREACHED(); |
| } |
| |
| return PROFILE_DISABLED; |
| } |