Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: chrome/browser/metrics/leak_detector/leak_detector_controller.cc

Issue 2062743002: Randomly enable leak detector based on probability parameter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use RenderThreadObserver interface to shutdown remote client on same thread Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/browser/metrics/leak_detector/leak_detector_controller.h" 5 #include "chrome/browser/metrics/leak_detector/leak_detector_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/rand_util.h"
10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
11 #include "components/metrics/leak_detector/gnu_build_id_reader.h" 12 #include "components/metrics/leak_detector/gnu_build_id_reader.h"
12 #include "components/variations/variations_associated_data.h" 13 #include "components/variations/variations_associated_data.h"
13 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
14 15
15 namespace metrics { 16 namespace metrics {
16 17
17 namespace { 18 namespace {
18 19
19 // Reads parameters for the field trial variation. Any parameters not present in 20 using ParamsMap = std::map<std::string, std::string>;
20 // the variation info or that cannot be parsed will be filled in with default 21
21 // values. Returns a MemoryLeakReportProto with the parameter fields filled in. 22 // Returns a mapping of param names to param values, obtained from the
22 MemoryLeakReportProto::Params GetVariationParameters() { 23 // variations system. Both names and values are strings.
24 ParamsMap GetRawVariationParams() {
25 const char kFieldTrialName[] = "RuntimeMemoryLeakDetector";
26 ParamsMap result;
27 variations::GetVariationParams(kFieldTrialName, &result);
28 return result;
29 }
30
31 // Reads the raw variation parameters and parses them to obtain values for the
32 // parameters used by the memory leak detector itself. Any parameters not
33 // present in the variation info or that cannot be parsed will be filled in with
34 // default values. Returns a MemoryLeakReportProto with the parameter fields
35 // filled in.
36 MemoryLeakReportProto::Params GetLeakDetectorParams() {
23 // Variation parameter names. 37 // Variation parameter names.
24 const char kFieldTrialName[] = "RuntimeMemoryLeakDetector";
25 const char kSamplingRateParam[] = "sampling_rate"; 38 const char kSamplingRateParam[] = "sampling_rate";
26 const char kMaxStackDepthParam[] = "max_stack_depth"; 39 const char kMaxStackDepthParam[] = "max_stack_depth";
27 const char kAnalysisIntervalKbParam[] = "analysis_interval_kb"; 40 const char kAnalysisIntervalKbParam[] = "analysis_interval_kb";
28 const char kSizeSuspicionThresholdParam[] = "size_suspicion_threshold"; 41 const char kSizeSuspicionThresholdParam[] = "size_suspicion_threshold";
29 const char kCallStackSuspicionThresholdParam[] = 42 const char kCallStackSuspicionThresholdParam[] =
30 "call_stack_suspicion_threshold"; 43 "call_stack_suspicion_threshold";
31 44
32 // Default parameter values. 45 // Default parameter values.
33 double kDefaultSamplingRate = 1.0f / 256; 46 double kDefaultSamplingRate = 1.0f / 256;
34 size_t kDefaultMaxStackDepth = 4; 47 size_t kDefaultMaxStackDepth = 4;
35 uint64_t kDefaultAnalysisIntervalKb = 32768; 48 uint64_t kDefaultAnalysisIntervalKb = 32768;
36 uint32_t kDefaultSizeSuspicionThreshold = 4; 49 uint32_t kDefaultSizeSuspicionThreshold = 4;
37 uint32_t kDefaultCallStackSuspicionThreshold = 4; 50 uint32_t kDefaultCallStackSuspicionThreshold = 4;
38 51
39 double sampling_rate = 0; 52 double sampling_rate = 0;
40 size_t max_stack_depth = 0; 53 size_t max_stack_depth = 0;
41 uint64_t analysis_interval_kb = 0; 54 uint64_t analysis_interval_kb = 0;
42 uint32_t size_suspicion_threshold = 0; 55 uint32_t size_suspicion_threshold = 0;
43 uint32_t call_stack_suspicion_threshold = 0; 56 uint32_t call_stack_suspicion_threshold = 0;
44 57
45 // Get a mapping of param names to param values. 58 const ParamsMap params = GetRawVariationParams();
46 std::map<std::string, std::string> params;
47 variations::GetVariationParams(kFieldTrialName, &params);
48 59
49 // Even if the variation param data does not exist and |params| ends up empty, 60 // Even if the variation param data does not exist and |params| ends up empty,
50 // the below code will assign default values. 61 // the below code will assign default values.
51 auto iter = params.find(kSamplingRateParam); 62 auto iter = params.find(kSamplingRateParam);
52 if (iter == params.end() || 63 if (iter == params.end() ||
53 !base::StringToDouble(iter->second, &sampling_rate)) { 64 !base::StringToDouble(iter->second, &sampling_rate)) {
54 sampling_rate = kDefaultSamplingRate; 65 sampling_rate = kDefaultSamplingRate;
55 } 66 }
56 67
57 iter = params.find(kMaxStackDepthParam); 68 iter = params.find(kMaxStackDepthParam);
(...skipping 22 matching lines...) Expand all
80 91
81 MemoryLeakReportProto_Params result; 92 MemoryLeakReportProto_Params result;
82 result.set_sampling_rate(sampling_rate); 93 result.set_sampling_rate(sampling_rate);
83 result.set_max_stack_depth(max_stack_depth); 94 result.set_max_stack_depth(max_stack_depth);
84 result.set_analysis_interval_bytes(analysis_interval_kb * 1024); 95 result.set_analysis_interval_bytes(analysis_interval_kb * 1024);
85 result.set_size_suspicion_threshold(size_suspicion_threshold); 96 result.set_size_suspicion_threshold(size_suspicion_threshold);
86 result.set_call_stack_suspicion_threshold(call_stack_suspicion_threshold); 97 result.set_call_stack_suspicion_threshold(call_stack_suspicion_threshold);
87 return result; 98 return result;
88 } 99 }
89 100
101 // Parses the parameters related to randomly enabling leak detector on different
102 // processes, from the raw parameter strings provided by the variations.
103 // Args:
104 // - browser_probability: probability that the leak detector will be enabled on
105 // browser process (spawned once per session).
106 // - renderer_probability: probability that the leak detector will be enabled on
107 // renderer process (spawned many times per session).
108 // - max_renderer_processes_enabled: The maximum number of renderer processes on
109 // which the leak detector can be enabled
110 // simultaneously.
111 //
112 // Probabilities are in the range [0, 1]. Anything higher or lower will not be
113 // clamped but it will not affect the outcome, since these probabilities are
114 // compared against the value of base::RandDouble() (aka the "dice roll"), which
115 // will be within this range.
116 void GetLeakDetectorEnableParams(double* browser_probability,
117 double* renderer_probability,
118 int* max_renderer_processes_enabled) {
119 const char kBrowserEnableProbabilityParam[] =
120 "browser_process_enable_probability";
121 const char kRendererEnableProbabilityParam[] =
122 "renderer_process_enable_probability";
123 const char kMaxRendererProcessesEnabledParam[] =
124 "max_renderer_processes_enabled";
125 const double kDefaultProbability = 0.0;
126 const int kDefaultNumProcessesEnabled = 0;
127
128 const ParamsMap params = GetRawVariationParams();
129 auto iter = params.find(kBrowserEnableProbabilityParam);
130 if (iter == params.end() ||
131 !base::StringToDouble(iter->second, browser_probability)) {
132 *browser_probability = kDefaultProbability;
133 }
134 iter = params.find(kRendererEnableProbabilityParam);
135 if (iter == params.end() ||
136 !base::StringToDouble(iter->second, renderer_probability)) {
137 *renderer_probability = kDefaultProbability;
138 }
139 iter = params.find(kMaxRendererProcessesEnabledParam);
140 if (iter == params.end() ||
141 !base::StringToInt(iter->second, max_renderer_processes_enabled)) {
142 *max_renderer_processes_enabled = kDefaultNumProcessesEnabled;
143 }
144 }
145
90 } // namespace 146 } // namespace
91 147
92 LeakDetectorController::LeakDetectorController() 148 LeakDetectorController::LeakDetectorController()
93 : params_(GetVariationParameters()) { 149 : params_(GetLeakDetectorParams()),
150 browser_process_enable_probability_(0),
151 renderer_process_enable_probability_(0),
152 max_renderer_processes_with_leak_detector_enabled_(0),
153 num_renderer_processes_with_leak_detector_enabled_(0) {
94 // Read the build ID once and store it. 154 // Read the build ID once and store it.
95 leak_detector::gnu_build_id_reader::ReadBuildID(&build_id_); 155 leak_detector::gnu_build_id_reader::ReadBuildID(&build_id_);
96 156
97 LeakDetector* detector = LeakDetector::GetInstance(); 157 GetLeakDetectorEnableParams(
98 detector->AddObserver(this); 158 &browser_process_enable_probability_,
159 &renderer_process_enable_probability_,
160 &max_renderer_processes_with_leak_detector_enabled_);
99 161
100 // Leak detector parameters are stored in |params_|. 162 // Register the LeakDetectorController with the remote controller, so this
101 detector->Init(params_, content::BrowserThread::GetTaskRunnerForThread( 163 // class can send/receive data to/from remote processes.
102 content::BrowserThread::UI)); 164 LeakDetectorRemoteController::SetLocalControllerInstance(this);
165
166 // Conditionally launch browser process based on probability.
167 if (base::RandDouble() < browser_process_enable_probability_) {
168 LeakDetector* detector = LeakDetector::GetInstance();
169 detector->AddObserver(this);
170
171 // Leak detector parameters are stored in |params_|.
172 detector->Init(params_, content::BrowserThread::GetTaskRunnerForThread(
173 content::BrowserThread::UI));
174 }
103 } 175 }
104 176
105 LeakDetectorController::~LeakDetectorController() { 177 LeakDetectorController::~LeakDetectorController() {
106 DCHECK(thread_checker_.CalledOnValidThread()); 178 DCHECK(thread_checker_.CalledOnValidThread());
107 LeakDetector::GetInstance()->RemoveObserver(this); 179 LeakDetector::GetInstance()->RemoveObserver(this);
108 } 180 }
109 181
110 void LeakDetectorController::GetLeakReports( 182 void LeakDetectorController::GetLeakReports(
111 std::vector<MemoryLeakReportProto>* reports) { 183 std::vector<MemoryLeakReportProto>* reports) {
112 DCHECK(thread_checker_.CalledOnValidThread()); 184 DCHECK(thread_checker_.CalledOnValidThread());
113 reports->swap(stored_reports_); 185 reports->swap(stored_reports_);
114 stored_reports_.clear(); 186 stored_reports_.clear();
115 } 187 }
116 188
117 void LeakDetectorController::OnLeaksFound( 189 void LeakDetectorController::OnLeaksFound(
118 const std::vector<MemoryLeakReportProto>& reports) { 190 const std::vector<MemoryLeakReportProto>& reports) {
119 StoreLeakReports(reports, MemoryLeakReportProto::BROWSER_PROCESS); 191 StoreLeakReports(reports, MemoryLeakReportProto::BROWSER_PROCESS);
120 } 192 }
121 193
122 MemoryLeakReportProto_Params LeakDetectorController::GetParams() const { 194 MemoryLeakReportProto_Params
123 return params_; 195 LeakDetectorController::GetParamsAndRecordRequest() {
196 if (ShouldRandomlyEnableLeakDetectorOnRendererProcess()) {
197 ++num_renderer_processes_with_leak_detector_enabled_;
198 return params_;
199 }
200 // If the leak detector is not to be enabled on the remote process, send an
201 // empty MemoryLeakReportProto_Params protobuf. The remote process will not
202 // initialize the leak detector since |sampling_rate| is 0.
203 return MemoryLeakReportProto_Params();
124 } 204 }
125 205
126 void LeakDetectorController::SendLeakReports( 206 void LeakDetectorController::SendLeakReports(
127 const std::vector<MemoryLeakReportProto>& reports) { 207 const std::vector<MemoryLeakReportProto>& reports) {
128 StoreLeakReports(reports, MemoryLeakReportProto::RENDERER_PROCESS); 208 StoreLeakReports(reports, MemoryLeakReportProto::RENDERER_PROCESS);
129 } 209 }
130 210
131 void LeakDetectorController::OnRemoteProcessShutdown() { 211 void LeakDetectorController::OnRemoteProcessShutdown() {
132 // TODO(sque): Handle remote process shutdown. 212 DCHECK_GT(num_renderer_processes_with_leak_detector_enabled_, 0);
213 --num_renderer_processes_with_leak_detector_enabled_;
214 }
215
216 bool LeakDetectorController::ShouldRandomlyEnableLeakDetectorOnRendererProcess()
217 const {
218 return base::RandDouble() < renderer_process_enable_probability_ &&
219 num_renderer_processes_with_leak_detector_enabled_ <
220 max_renderer_processes_with_leak_detector_enabled_;
133 } 221 }
134 222
135 void LeakDetectorController::StoreLeakReports( 223 void LeakDetectorController::StoreLeakReports(
136 const std::vector<MemoryLeakReportProto>& reports, 224 const std::vector<MemoryLeakReportProto>& reports,
137 MemoryLeakReportProto::ProcessType process_type) { 225 MemoryLeakReportProto::ProcessType process_type) {
138 DCHECK(thread_checker_.CalledOnValidThread()); 226 DCHECK(thread_checker_.CalledOnValidThread());
139 227
140 for (const auto& report : reports) { 228 for (const auto& report : reports) {
141 // Store the report and insert stored parameters. 229 // Store the report and insert stored parameters.
142 stored_reports_.push_back(report); 230 stored_reports_.push_back(report);
143 stored_reports_.back().mutable_params()->CopyFrom(params_); 231 stored_reports_.back().mutable_params()->CopyFrom(params_);
144 stored_reports_.back().set_source_process(process_type); 232 stored_reports_.back().set_source_process(process_type);
145 stored_reports_.back().mutable_build_id()->assign(build_id_.begin(), 233 stored_reports_.back().mutable_build_id()->assign(build_id_.begin(),
146 build_id_.end()); 234 build_id_.end());
147 } 235 }
148 } 236 }
149 237
150 } // namespace metrics 238 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698