Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/stack_sampling_configuration.h" | 5 #include "chrome/common/stack_sampling_configuration.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | |
| 8 #include "base/lazy_instance.h" | |
| 7 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 8 #include "chrome/common/channel_info.h" | 10 #include "chrome/common/channel_info.h" |
| 11 #include "chrome/common/chrome_switches.h" | |
| 9 #include "components/version_info/version_info.h" | 12 #include "components/version_info/version_info.h" |
| 13 #include "content/public/common/content_switches.h" | |
| 10 | 14 |
| 11 namespace { | 15 namespace { |
| 12 | 16 |
| 17 static base::LazyInstance<StackSamplingConfiguration>::Leaky g_configuration = | |
| 18 LAZY_INSTANCE_INITIALIZER; | |
| 19 | |
| 13 // The profiler is currently only implemented for Windows x64, and only runs on | 20 // The profiler is currently only implemented for Windows x64, and only runs on |
| 14 // trunk, canary, and dev. | 21 // trunk, canary, and dev. |
| 15 bool IsProfilerSupported() { | 22 bool IsProfilerSupported() { |
| 16 #if !defined(_WIN64) | 23 #if !defined(_WIN64) |
| 17 return false; | 24 return false; |
| 18 #else | 25 #else |
| 19 const version_info::Channel channel = chrome::GetChannel(); | 26 const version_info::Channel channel = chrome::GetChannel(); |
| 20 return (channel == version_info::Channel::UNKNOWN || | 27 return (channel == version_info::Channel::UNKNOWN || |
| 21 channel == version_info::Channel::CANARY || | 28 channel == version_info::Channel::CANARY || |
| 22 channel == version_info::Channel::DEV); | 29 channel == version_info::Channel::DEV); |
| 23 #endif | 30 #endif |
| 24 } | 31 } |
| 25 | 32 |
| 33 bool ExecutingInBrowserProcess() { | |
|
Ilya Sherman
2016/09/28 01:02:15
nit: I'd prepend an "Is" to this name. And, pleas
Mike Wittman
2016/09/28 19:34:26
Changed to IsBrowserProcess. IsExecutingInBrowserP
| |
| 34 const base::CommandLine* command_line = | |
| 35 base::CommandLine::ForCurrentProcess(); | |
| 36 std::string process_type = | |
| 37 command_line->GetSwitchValueASCII(switches::kProcessType); | |
| 38 return process_type.empty(); | |
| 39 } | |
| 40 | |
| 26 } // namespace | 41 } // namespace |
| 27 | 42 |
| 28 StackSamplingConfiguration::StackSamplingConfiguration() | 43 StackSamplingConfiguration::StackSamplingConfiguration() |
| 29 : configuration_(GenerateConfiguration()) { | 44 : configuration_(GenerateConfiguration()) { |
| 30 } | 45 } |
| 31 | 46 |
| 32 base::StackSamplingProfiler::SamplingParams | 47 base::StackSamplingProfiler::SamplingParams |
| 33 StackSamplingConfiguration::GetSamplingParams() const { | 48 StackSamplingConfiguration::GetSamplingParamsForCurrentProcess() const { |
| 34 base::StackSamplingProfiler::SamplingParams params; | 49 base::StackSamplingProfiler::SamplingParams params; |
| 35 params.bursts = 1; | 50 params.bursts = 1; |
| 36 const base::TimeDelta duration = base::TimeDelta::FromSeconds(30); | 51 params.initial_delay = base::TimeDelta::FromMilliseconds(0); |
| 52 params.sampling_interval = base::TimeDelta::FromMilliseconds(0); | |
| 53 params.samples_per_burst = 0; | |
| 37 | 54 |
| 38 switch (configuration_) { | 55 if (IsProfilerEnabledForCurrentProcess()) { |
| 39 case PROFILE_DISABLED: | 56 const base::TimeDelta duration = base::TimeDelta::FromSeconds(30); |
| 40 case PROFILE_CONTROL: | 57 params.sampling_interval = base::TimeDelta::FromMilliseconds(100); |
| 41 params.initial_delay = base::TimeDelta::FromMilliseconds(0); | 58 params.samples_per_burst = duration / params.sampling_interval; |
| 42 params.sampling_interval = base::TimeDelta::FromMilliseconds(0); | 59 } |
| 43 params.samples_per_burst = 0; | |
| 44 break; | |
| 45 | 60 |
| 46 case PROFILE_NO_SAMPLES: | |
| 47 params.initial_delay = duration; | |
| 48 params.sampling_interval = base::TimeDelta::FromMilliseconds(0); | |
| 49 params.samples_per_burst = 0; | |
| 50 break; | |
| 51 | |
| 52 case PROFILE_5HZ: | |
| 53 params.initial_delay = base::TimeDelta::FromMilliseconds(0); | |
| 54 params.sampling_interval = base::TimeDelta::FromMilliseconds(200); | |
| 55 params.samples_per_burst = duration / params.sampling_interval; | |
| 56 break; | |
| 57 | |
| 58 case PROFILE_10HZ: | |
| 59 params.initial_delay = base::TimeDelta::FromMilliseconds(0); | |
| 60 params.sampling_interval = base::TimeDelta::FromMilliseconds(100); | |
| 61 params.samples_per_burst = duration / params.sampling_interval; | |
| 62 break; | |
| 63 | |
| 64 case PROFILE_100HZ: | |
| 65 params.initial_delay = base::TimeDelta::FromMilliseconds(0); | |
| 66 params.sampling_interval = base::TimeDelta::FromMilliseconds(10); | |
| 67 params.samples_per_burst = duration / params.sampling_interval; | |
| 68 break; | |
| 69 } | |
| 70 return params; | 61 return params; |
| 71 } | 62 } |
| 72 | 63 |
| 73 bool StackSamplingConfiguration::IsProfilerEnabled() const { | 64 bool StackSamplingConfiguration::IsProfilerEnabledForCurrentProcess() const { |
| 74 return (configuration_ != PROFILE_DISABLED && | 65 if (ExecutingInBrowserProcess()) { |
| 75 configuration_ != PROFILE_CONTROL); | 66 return configuration_ == PROFILE_BROWSER_PROCESS || |
| 67 configuration_ == PROFILE_BROWSER_AND_GPU_PROCESS; | |
| 68 } | |
| 69 | |
| 70 DCHECK(configuration_ == PROFILE_FROM_COMMAND_LINE); | |
|
Ilya Sherman
2016/09/28 01:02:15
nit: DCHECK_EQ
Mike Wittman
2016/09/28 19:34:26
Done.
| |
| 71 // This is a child process. The kStartStackProfiler switch passed by the | |
| 72 // browser process determines whether the profiler is enabled for the process. | |
| 73 const base::CommandLine* command_line = | |
| 74 base::CommandLine::ForCurrentProcess(); | |
| 75 return command_line->HasSwitch(switches::kStartStackProfiler); | |
| 76 } | 76 } |
| 77 | 77 |
| 78 void StackSamplingConfiguration::RegisterSyntheticFieldTrial( | 78 void StackSamplingConfiguration::RegisterSyntheticFieldTrial( |
| 79 const RegisterSyntheticFieldTrialFunction& register_field_trial) const { | 79 const RegisterSyntheticFieldTrialFunction& register_field_trial) const { |
| 80 DCHECK(ExecutingInBrowserProcess()); | |
| 81 | |
| 80 if (!IsProfilerSupported()) | 82 if (!IsProfilerSupported()) |
| 81 return; | 83 return; |
| 82 | 84 |
| 83 std::string group; | 85 std::string group; |
| 84 switch (configuration_) { | 86 switch (configuration_) { |
| 85 case PROFILE_DISABLED: | 87 case PROFILE_DISABLED: |
| 86 group = "Disabled"; | 88 group = "Disabled"; |
| 87 break; | 89 break; |
| 88 | 90 |
| 89 case PROFILE_CONTROL: | 91 case PROFILE_CONTROL: |
| 90 group = "Control"; | 92 group = "Control"; |
| 91 break; | 93 break; |
| 92 | 94 |
| 93 case PROFILE_NO_SAMPLES: | 95 case PROFILE_BROWSER_PROCESS: |
| 94 group = "NoSamples"; | 96 group = "BrowserProcess"; |
| 95 break; | 97 break; |
| 96 | 98 |
| 97 case PROFILE_5HZ: | 99 case PROFILE_GPU_PROCESS: |
| 98 group = "5Hz"; | 100 group = "GpuProcess"; |
| 99 break; | 101 break; |
| 100 | 102 |
| 101 case PROFILE_10HZ: | 103 case PROFILE_BROWSER_AND_GPU_PROCESS: |
| 102 group = "10Hz"; | 104 group = "BrowserAndGpuProcess"; |
| 103 break; | 105 break; |
| 104 | 106 |
| 105 case PROFILE_100HZ: | 107 case PROFILE_FROM_COMMAND_LINE: |
| 106 group = "100Hz"; | 108 NOTREACHED(); |
| 107 break; | 109 break; |
| 108 } | 110 } |
| 109 | 111 |
| 110 register_field_trial.Run("SyntheticStackProfilingConfiguration", group); | 112 register_field_trial.Run("SyntheticStackProfilingConfiguration", group); |
| 111 } | 113 } |
| 112 | 114 |
| 115 void StackSamplingConfiguration::AppendCommandLineSwitchForChildProcess( | |
| 116 const std::string process_type, | |
| 117 base::CommandLine* command_line) const { | |
| 118 DCHECK(ExecutingInBrowserProcess()); | |
| 119 | |
| 120 if (process_type == switches::kGpuProcess && | |
| 121 (configuration_ == PROFILE_GPU_PROCESS || | |
| 122 configuration_ == PROFILE_BROWSER_AND_GPU_PROCESS)) { | |
| 123 command_line->AppendSwitch(switches::kStartStackProfiler); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 // static | |
| 128 StackSamplingConfiguration* StackSamplingConfiguration::Get() { | |
| 129 return g_configuration.Pointer(); | |
| 130 } | |
| 131 | |
| 113 // static | 132 // static |
| 114 StackSamplingConfiguration::ProfileConfiguration | 133 StackSamplingConfiguration::ProfileConfiguration |
| 115 StackSamplingConfiguration::GenerateConfiguration() { | 134 StackSamplingConfiguration::GenerateConfiguration() { |
| 135 if (!ExecutingInBrowserProcess()) | |
| 136 return PROFILE_FROM_COMMAND_LINE; | |
| 137 | |
| 116 if (!IsProfilerSupported()) | 138 if (!IsProfilerSupported()) |
| 117 return PROFILE_DISABLED; | 139 return PROFILE_DISABLED; |
| 118 | 140 |
| 119 // Enable the profiler in the intended ultimate production configuration for | 141 // Enable the profiler in the ultimate production configuration for |
| 120 // development/waterfall builds. | 142 // development/waterfall builds. |
| 121 if (chrome::GetChannel() == version_info::Channel::UNKNOWN) | 143 if (chrome::GetChannel() == version_info::Channel::UNKNOWN) |
| 122 return PROFILE_10HZ; | 144 return PROFILE_BROWSER_AND_GPU_PROCESS; |
| 123 | 145 |
| 124 // Enable according to the variations below in canary and dev. | 146 // Enable according to the variations below in canary and dev. |
| 125 if (chrome::GetChannel() == version_info::Channel::CANARY || | 147 if (chrome::GetChannel() == version_info::Channel::CANARY || |
| 126 chrome::GetChannel() == version_info::Channel::DEV) { | 148 chrome::GetChannel() == version_info::Channel::DEV) { |
| 127 struct Variation { | 149 struct Variation { |
| 128 ProfileConfiguration config; | 150 ProfileConfiguration config; |
| 129 int weight; | 151 int weight; |
| 130 }; | 152 }; |
| 131 | 153 |
| 132 // Generate a configuration according to the associated weights. | 154 // Generate a configuration according to the associated weights. |
| 133 const Variation variations[] = { | 155 const Variation variations[] = { |
| 134 { PROFILE_10HZ, 100}, | 156 { PROFILE_BROWSER_PROCESS, 100}, |
| 157 { PROFILE_GPU_PROCESS, 0}, | |
| 158 { PROFILE_BROWSER_AND_GPU_PROCESS, 0}, | |
| 135 { PROFILE_CONTROL, 0}, | 159 { PROFILE_CONTROL, 0}, |
| 136 { PROFILE_DISABLED, 0} | 160 { PROFILE_DISABLED, 0} |
| 137 }; | 161 }; |
| 138 | 162 |
| 139 int total_weight = 0; | 163 int total_weight = 0; |
| 140 for (const Variation& variation : variations) | 164 for (const Variation& variation : variations) |
| 141 total_weight += variation.weight; | 165 total_weight += variation.weight; |
| 142 DCHECK_EQ(100, total_weight); | 166 DCHECK_EQ(100, total_weight); |
| 143 | 167 |
| 144 int chosen = base::RandInt(0, total_weight - 1); // Max is inclusive. | 168 int chosen = base::RandInt(0, total_weight - 1); // Max is inclusive. |
| 145 int cumulative_weight = 0; | 169 int cumulative_weight = 0; |
| 146 for (const Variation& variation : variations) { | 170 for (const Variation& variation : variations) { |
| 147 if (chosen >= cumulative_weight && | 171 if (chosen >= cumulative_weight && |
| 148 chosen < cumulative_weight + variation.weight) { | 172 chosen < cumulative_weight + variation.weight) { |
| 149 return variation.config; | 173 return variation.config; |
| 150 } | 174 } |
| 151 cumulative_weight += variation.weight; | 175 cumulative_weight += variation.weight; |
| 152 } | 176 } |
| 153 NOTREACHED(); | 177 NOTREACHED(); |
| 154 } | 178 } |
| 155 | 179 |
| 156 return PROFILE_DISABLED; | 180 return PROFILE_DISABLED; |
| 157 } | 181 } |
| OLD | NEW |