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 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 // Returns true if the current execution is taking place in the browser process. |
| 34 bool IsBrowserProcess() { |
| 35 const base::CommandLine* command_line = |
| 36 base::CommandLine::ForCurrentProcess(); |
| 37 std::string process_type = |
| 38 command_line->GetSwitchValueASCII(switches::kProcessType); |
| 39 return process_type.empty(); |
| 40 } |
| 41 |
26 } // namespace | 42 } // namespace |
27 | 43 |
28 StackSamplingConfiguration::StackSamplingConfiguration() | 44 StackSamplingConfiguration::StackSamplingConfiguration() |
29 : configuration_(GenerateConfiguration()) { | 45 : configuration_(GenerateConfiguration()) { |
30 } | 46 } |
31 | 47 |
32 base::StackSamplingProfiler::SamplingParams | 48 base::StackSamplingProfiler::SamplingParams |
33 StackSamplingConfiguration::GetSamplingParams() const { | 49 StackSamplingConfiguration::GetSamplingParamsForCurrentProcess() const { |
34 base::StackSamplingProfiler::SamplingParams params; | 50 base::StackSamplingProfiler::SamplingParams params; |
35 params.bursts = 1; | 51 params.bursts = 1; |
36 const base::TimeDelta duration = base::TimeDelta::FromSeconds(30); | 52 params.initial_delay = base::TimeDelta::FromMilliseconds(0); |
| 53 params.sampling_interval = base::TimeDelta::FromMilliseconds(0); |
| 54 params.samples_per_burst = 0; |
37 | 55 |
38 switch (configuration_) { | 56 if (IsProfilerEnabledForCurrentProcess()) { |
39 case PROFILE_DISABLED: | 57 const base::TimeDelta duration = base::TimeDelta::FromSeconds(30); |
40 case PROFILE_CONTROL: | 58 params.sampling_interval = base::TimeDelta::FromMilliseconds(100); |
41 params.initial_delay = base::TimeDelta::FromMilliseconds(0); | 59 params.samples_per_burst = duration / params.sampling_interval; |
42 params.sampling_interval = base::TimeDelta::FromMilliseconds(0); | 60 } |
43 params.samples_per_burst = 0; | |
44 break; | |
45 | 61 |
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; | 62 return params; |
71 } | 63 } |
72 | 64 |
73 bool StackSamplingConfiguration::IsProfilerEnabled() const { | 65 bool StackSamplingConfiguration::IsProfilerEnabledForCurrentProcess() const { |
74 return (configuration_ != PROFILE_DISABLED && | 66 if (IsBrowserProcess()) { |
75 configuration_ != PROFILE_CONTROL); | 67 return configuration_ == PROFILE_BROWSER_PROCESS || |
| 68 configuration_ == PROFILE_BROWSER_AND_GPU_PROCESS; |
| 69 } |
| 70 |
| 71 DCHECK_EQ(PROFILE_FROM_COMMAND_LINE, configuration_); |
| 72 // This is a child process. The |kStartStackProfiler| switch passed by the |
| 73 // browser process determines whether the profiler is enabled for the process. |
| 74 const base::CommandLine* command_line = |
| 75 base::CommandLine::ForCurrentProcess(); |
| 76 return command_line->HasSwitch(switches::kStartStackProfiler); |
76 } | 77 } |
77 | 78 |
78 bool StackSamplingConfiguration::GetSyntheticFieldTrial( | 79 bool StackSamplingConfiguration::GetSyntheticFieldTrial( |
79 std::string* trial_name, | 80 std::string* trial_name, |
80 std::string* group_name) const { | 81 std::string* group_name) const { |
| 82 DCHECK(IsBrowserProcess()); |
| 83 |
81 if (!IsProfilerSupported()) | 84 if (!IsProfilerSupported()) |
82 return false; | 85 return false; |
83 | 86 |
84 *trial_name = "SyntheticStackProfilingConfiguration"; | 87 *trial_name = "SyntheticStackProfilingConfiguration"; |
85 *group_name = std::string(); | 88 *group_name = std::string(); |
86 switch (configuration_) { | 89 switch (configuration_) { |
87 case PROFILE_DISABLED: | 90 case PROFILE_DISABLED: |
88 *group_name = "Disabled"; | 91 *group_name = "Disabled"; |
89 break; | 92 break; |
90 | 93 |
91 case PROFILE_CONTROL: | 94 case PROFILE_CONTROL: |
92 *group_name = "Control"; | 95 *group_name = "Control"; |
93 break; | 96 break; |
94 | 97 |
95 case PROFILE_NO_SAMPLES: | 98 case PROFILE_BROWSER_PROCESS: |
96 *group_name = "NoSamples"; | 99 *group_name = "BrowserProcess"; |
97 break; | 100 break; |
98 | 101 |
99 case PROFILE_5HZ: | 102 case PROFILE_GPU_PROCESS: |
100 *group_name = "5Hz"; | 103 *group_name = "GpuProcess"; |
101 break; | 104 break; |
102 | 105 |
103 case PROFILE_10HZ: | 106 case PROFILE_BROWSER_AND_GPU_PROCESS: |
104 *group_name = "10Hz"; | 107 *group_name = "BrowserAndGpuProcess"; |
105 break; | 108 break; |
106 | 109 |
107 case PROFILE_100HZ: | 110 case PROFILE_FROM_COMMAND_LINE: |
108 *group_name = "100Hz"; | 111 NOTREACHED(); |
109 break; | 112 break; |
110 } | 113 } |
111 | 114 |
112 return !group_name->empty(); | 115 return !group_name->empty(); |
113 } | 116 } |
114 | 117 |
| 118 void StackSamplingConfiguration::AppendCommandLineSwitchForChildProcess( |
| 119 const std::string& process_type, |
| 120 base::CommandLine* command_line) const { |
| 121 DCHECK(IsBrowserProcess()); |
| 122 |
| 123 if (process_type == switches::kGpuProcess && |
| 124 (configuration_ == PROFILE_GPU_PROCESS || |
| 125 configuration_ == PROFILE_BROWSER_AND_GPU_PROCESS)) { |
| 126 command_line->AppendSwitch(switches::kStartStackProfiler); |
| 127 } |
| 128 } |
| 129 |
| 130 // static |
| 131 StackSamplingConfiguration* StackSamplingConfiguration::Get() { |
| 132 return g_configuration.Pointer(); |
| 133 } |
| 134 |
115 // static | 135 // static |
116 StackSamplingConfiguration::ProfileConfiguration | 136 StackSamplingConfiguration::ProfileConfiguration |
117 StackSamplingConfiguration::GenerateConfiguration() { | 137 StackSamplingConfiguration::GenerateConfiguration() { |
| 138 if (!IsBrowserProcess()) |
| 139 return PROFILE_FROM_COMMAND_LINE; |
| 140 |
118 if (!IsProfilerSupported()) | 141 if (!IsProfilerSupported()) |
119 return PROFILE_DISABLED; | 142 return PROFILE_DISABLED; |
120 | 143 |
121 // Enable the profiler in the intended ultimate production configuration for | 144 // Enable the profiler in the ultimate production configuration for |
122 // development/waterfall builds. | 145 // development/waterfall builds. |
123 if (chrome::GetChannel() == version_info::Channel::UNKNOWN) | 146 if (chrome::GetChannel() == version_info::Channel::UNKNOWN) |
124 return PROFILE_10HZ; | 147 return PROFILE_BROWSER_AND_GPU_PROCESS; |
125 | 148 |
126 // Enable according to the variations below in canary and dev. | 149 // Enable according to the variations below in canary and dev. |
127 if (chrome::GetChannel() == version_info::Channel::CANARY || | 150 if (chrome::GetChannel() == version_info::Channel::CANARY || |
128 chrome::GetChannel() == version_info::Channel::DEV) { | 151 chrome::GetChannel() == version_info::Channel::DEV) { |
129 struct Variation { | 152 struct Variation { |
130 ProfileConfiguration config; | 153 ProfileConfiguration config; |
131 int weight; | 154 int weight; |
132 }; | 155 }; |
133 | 156 |
134 // Generate a configuration according to the associated weights. | 157 // Generate a configuration according to the associated weights. |
135 const Variation variations[] = { | 158 const Variation variations[] = { |
136 { PROFILE_10HZ, 100}, | 159 { PROFILE_BROWSER_PROCESS, 100}, |
| 160 { PROFILE_GPU_PROCESS, 0}, |
| 161 { PROFILE_BROWSER_AND_GPU_PROCESS, 0}, |
137 { PROFILE_CONTROL, 0}, | 162 { PROFILE_CONTROL, 0}, |
138 { PROFILE_DISABLED, 0} | 163 { PROFILE_DISABLED, 0} |
139 }; | 164 }; |
140 | 165 |
141 int total_weight = 0; | 166 int total_weight = 0; |
142 for (const Variation& variation : variations) | 167 for (const Variation& variation : variations) |
143 total_weight += variation.weight; | 168 total_weight += variation.weight; |
144 DCHECK_EQ(100, total_weight); | 169 DCHECK_EQ(100, total_weight); |
145 | 170 |
146 int chosen = base::RandInt(0, total_weight - 1); // Max is inclusive. | 171 int chosen = base::RandInt(0, total_weight - 1); // Max is inclusive. |
147 int cumulative_weight = 0; | 172 int cumulative_weight = 0; |
148 for (const Variation& variation : variations) { | 173 for (const Variation& variation : variations) { |
149 if (chosen >= cumulative_weight && | 174 if (chosen >= cumulative_weight && |
150 chosen < cumulative_weight + variation.weight) { | 175 chosen < cumulative_weight + variation.weight) { |
151 return variation.config; | 176 return variation.config; |
152 } | 177 } |
153 cumulative_weight += variation.weight; | 178 cumulative_weight += variation.weight; |
154 } | 179 } |
155 NOTREACHED(); | 180 NOTREACHED(); |
156 } | 181 } |
157 | 182 |
158 return PROFILE_DISABLED; | 183 return PROFILE_DISABLED; |
159 } | 184 } |
OLD | NEW |