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

Side by Side Diff: components/metrics/call_stack_profile_metrics_provider.cc

Issue 2927593002: Make stack sampling profiler sample beyond startup. (Closed)
Patch Set: Created 3 years, 6 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 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 "components/metrics/call_stack_profile_metrics_provider.h" 5 #include "components/metrics/call_stack_profile_metrics_provider.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <cstring> 11 #include <cstring>
12 #include <map> 12 #include <map>
13 #include <string> 13 #include <string>
14 #include <utility> 14 #include <utility>
15 #include <vector> 15 #include <vector>
16 16
17 #include "base/bind.h" 17 #include "base/bind.h"
18 #include "base/location.h" 18 #include "base/location.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/macros.h" 20 #include "base/macros.h"
21 #include "base/memory/singleton.h" 21 #include "base/memory/singleton.h"
22 #include "base/metrics/field_trial.h" 22 #include "base/metrics/field_trial_params.h"
23 #include "base/metrics/metrics_hashes.h" 23 #include "base/metrics/metrics_hashes.h"
24 #include "base/profiler/stack_sampling_profiler.h" 24 #include "base/profiler/stack_sampling_profiler.h"
25 #include "base/single_thread_task_runner.h" 25 #include "base/single_thread_task_runner.h"
26 #include "base/synchronization/lock.h" 26 #include "base/synchronization/lock.h"
27 #include "base/threading/thread_task_runner_handle.h" 27 #include "base/threading/thread_task_runner_handle.h"
28 #include "base/time/time.h" 28 #include "base/time/time.h"
29 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" 29 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h"
30 30
31 using base::StackSamplingProfiler; 31 using base::StackSamplingProfiler;
32 32
(...skipping 16 matching lines...) Expand all
49 49
50 ProcessPhase::SHUTDOWN_START, 50 ProcessPhase::SHUTDOWN_START,
51 }; 51 };
52 52
53 // ProfilesState -------------------------------------------------------------- 53 // ProfilesState --------------------------------------------------------------
54 54
55 // A set of profiles and the CallStackProfileMetricsProvider state associated 55 // A set of profiles and the CallStackProfileMetricsProvider state associated
56 // with them. 56 // with them.
57 struct ProfilesState { 57 struct ProfilesState {
58 ProfilesState(const CallStackProfileParams& params, 58 ProfilesState(const CallStackProfileParams& params,
59 StackSamplingProfiler::CallStackProfiles profiles, 59 StackSamplingProfiler::CallStackProfiles profiles);
60 base::TimeTicks start_timestamp);
61 ProfilesState(ProfilesState&&); 60 ProfilesState(ProfilesState&&);
62 ProfilesState& operator=(ProfilesState&&); 61 ProfilesState& operator=(ProfilesState&&);
63 62
64 // The metrics-related parameters provided to 63 // The metrics-related parameters provided to
65 // CallStackProfileMetricsProvider::GetProfilerCallback(). 64 // CallStackProfileMetricsProvider::GetProfilerCallback().
66 CallStackProfileParams params; 65 CallStackProfileParams params;
67 66
68 // The call stack profiles collected by the profiler. 67 // The call stack profiles collected by the profiler.
69 StackSamplingProfiler::CallStackProfiles profiles; 68 StackSamplingProfiler::CallStackProfiles profiles;
70 69
71 // The time at which the CallStackProfileMetricsProvider became aware of the
72 // request for profiling. In particular, this is when callback was requested
73 // via CallStackProfileMetricsProvider::GetProfilerCallback(). Used to
74 // determine if collection was disabled during the collection of the profile.
75 base::TimeTicks start_timestamp;
76
77 private: 70 private:
78 DISALLOW_COPY_AND_ASSIGN(ProfilesState); 71 DISALLOW_COPY_AND_ASSIGN(ProfilesState);
79 }; 72 };
80 73
81 ProfilesState::ProfilesState(const CallStackProfileParams& params, 74 ProfilesState::ProfilesState(const CallStackProfileParams& params,
82 StackSamplingProfiler::CallStackProfiles profiles, 75 StackSamplingProfiler::CallStackProfiles profiles)
83 base::TimeTicks start_timestamp) 76 : params(params), profiles(std::move(profiles)) {}
84 : params(params),
85 profiles(std::move(profiles)),
86 start_timestamp(start_timestamp) {}
87 77
88 ProfilesState::ProfilesState(ProfilesState&&) = default; 78 ProfilesState::ProfilesState(ProfilesState&&) = default;
89 79
90 // Some versions of GCC need this for push_back to work with std::move. 80 // Some versions of GCC need this for push_back to work with std::move.
91 ProfilesState& ProfilesState::operator=(ProfilesState&&) = default; 81 ProfilesState& ProfilesState::operator=(ProfilesState&&) = default;
92 82
93 // PendingProfiles ------------------------------------------------------------ 83 // PendingProfiles ------------------------------------------------------------
94 84
95 // Singleton class responsible for retaining profiles received via the callback 85 // Singleton class responsible for retaining profiles received via the callback
96 // created by CallStackProfileMetricsProvider::GetProfilerCallback(). These are 86 // created by CallStackProfileMetricsProvider::GetProfilerCallback(). These are
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 163 }
174 164
175 void PendingProfiles::CollectProfilesIfCollectionEnabled( 165 void PendingProfiles::CollectProfilesIfCollectionEnabled(
176 ProfilesState profiles) { 166 ProfilesState profiles) {
177 base::AutoLock scoped_lock(lock_); 167 base::AutoLock scoped_lock(lock_);
178 168
179 // Only collect if collection is not disabled and hasn't been disabled 169 // Only collect if collection is not disabled and hasn't been disabled
180 // since the start of collection for this profile. 170 // since the start of collection for this profile.
181 if (!collection_enabled_ || 171 if (!collection_enabled_ ||
182 (!last_collection_disable_time_.is_null() && 172 (!last_collection_disable_time_.is_null() &&
183 last_collection_disable_time_ >= profiles.start_timestamp)) { 173 last_collection_disable_time_ >= profiles.params.start_timestamp)) {
184 return; 174 return;
185 } 175 }
186 176
187 profiles_.push_back(std::move(profiles)); 177 profiles_.push_back(std::move(profiles));
188 } 178 }
189 179
190 void PendingProfiles::ResetToDefaultStateForTesting() { 180 void PendingProfiles::ResetToDefaultStateForTesting() {
191 base::AutoLock scoped_lock(lock_); 181 base::AutoLock scoped_lock(lock_);
192 182
193 collection_enabled_ = true; 183 collection_enabled_ = true;
194 last_collection_disable_time_ = base::TimeTicks(); 184 last_collection_disable_time_ = base::TimeTicks();
195 profiles_.clear(); 185 profiles_.clear();
196 } 186 }
197 187
198 // |collection_enabled_| is initialized to true to collect any profiles that are 188 // |collection_enabled_| is initialized to true to collect any profiles that are
199 // generated prior to creation of the CallStackProfileMetricsProvider. The 189 // generated prior to creation of the CallStackProfileMetricsProvider. The
200 // ultimate disposition of these pre-creation collected profiles will be 190 // ultimate disposition of these pre-creation collected profiles will be
201 // determined by the initial recording state provided to 191 // determined by the initial recording state provided to
202 // CallStackProfileMetricsProvider. 192 // CallStackProfileMetricsProvider.
203 PendingProfiles::PendingProfiles() : collection_enabled_(true) {} 193 PendingProfiles::PendingProfiles() : collection_enabled_(true) {}
204 194
205 PendingProfiles::~PendingProfiles() {} 195 PendingProfiles::~PendingProfiles() {}
206 196
207 // Functions to process completed profiles ------------------------------------ 197 // Functions to process completed profiles ------------------------------------
208 198
209 // Will be invoked on either the main thread or the profiler's thread. Provides 199 // Will be invoked on either the main thread or the profiler's thread. Provides
210 // the profiles to PendingProfiles to append, if the collecting state allows. 200 // the profiles to PendingProfiles to append, if the collecting state allows.
211 void ReceiveCompletedProfilesImpl( 201 bool ReceiveCompletedProfilesImpl(
212 const CallStackProfileParams& params, 202 CallStackProfileParams* params,
213 base::TimeTicks start_timestamp, 203 StackSamplingProfiler::CallStackProfiles profiles,
214 StackSamplingProfiler::CallStackProfiles profiles) { 204 StackSamplingProfiler::SamplingParams* sampling_params) {
215 PendingProfiles::GetInstance()->CollectProfilesIfCollectionEnabled( 205 PendingProfiles::GetInstance()->CollectProfilesIfCollectionEnabled(
216 ProfilesState(params, std::move(profiles), start_timestamp)); 206 ProfilesState(*params, std::move(profiles)));
207
208 // Now, schedule periodic sampling every 1s, if enabled by trial.
209 if (sampling_params &&
210 CallStackProfileMetricsProvider::IsPeriodicSamplingEnabled() &&
211 params->process == CallStackProfileParams::BROWSER_PROCESS &&
212 params->thread == CallStackProfileParams::UI_THREAD) {
213 params->trigger = metrics::CallStackProfileParams::PERIODIC_COLLECTION;
214 params->start_timestamp = base::TimeTicks::Now();
215 sampling_params->initial_delay = base::TimeDelta::FromSeconds(1);
216 sampling_params->bursts = 1;
217 sampling_params->samples_per_burst = 1;
218 // Below are unused:
219 sampling_params->burst_interval = base::TimeDelta::FromMilliseconds(0);
220 sampling_params->sampling_interval = base::TimeDelta::FromMilliseconds(0);
221 return true;
222 }
223 return false;
217 } 224 }
218 225
219 // Invoked on an arbitrary thread. Ignores the provided profiles. 226 // Invoked on an arbitrary thread. Ignores the provided profiles.
220 void IgnoreCompletedProfiles( 227 bool IgnoreCompletedProfiles(
221 StackSamplingProfiler::CallStackProfiles profiles) {} 228 StackSamplingProfiler::CallStackProfiles profiles,
229 StackSamplingProfiler::SamplingParams* sampling_params) {
230 return false;
231 }
222 232
223 // Functions to encode protobufs ---------------------------------------------- 233 // Functions to encode protobufs ----------------------------------------------
224 234
225 // The protobuf expects the MD5 checksum prefix of the module name. 235 // The protobuf expects the MD5 checksum prefix of the module name.
226 uint64_t HashModuleFilename(const base::FilePath& filename) { 236 uint64_t HashModuleFilename(const base::FilePath& filename) {
227 const base::FilePath::StringType basename = filename.BaseName().value(); 237 const base::FilePath::StringType basename = filename.BaseName().value();
228 // Copy the bytes in basename into a string buffer. 238 // Copy the bytes in basename into a string buffer.
229 size_t basename_length_in_bytes = 239 size_t basename_length_in_bytes =
230 basename.size() * sizeof(base::FilePath::CharType); 240 basename.size() * sizeof(base::FilePath::CharType);
231 std::string name_bytes(basename_length_in_bytes, '\0'); 241 std::string name_bytes(basename_length_in_bytes, '\0');
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 for (const StackSamplingProfiler::Module& module : profile.modules) { 334 for (const StackSamplingProfiler::Module& module : profile.modules) {
325 CallStackProfile::ModuleIdentifier* module_id = 335 CallStackProfile::ModuleIdentifier* module_id =
326 proto_profile->add_module_id(); 336 proto_profile->add_module_id();
327 module_id->set_build_id(module.id); 337 module_id->set_build_id(module.id);
328 module_id->set_name_md5_prefix(HashModuleFilename(module.filename)); 338 module_id->set_name_md5_prefix(HashModuleFilename(module.filename));
329 } 339 }
330 340
331 proto_profile->set_profile_duration_ms( 341 proto_profile->set_profile_duration_ms(
332 profile.profile_duration.InMilliseconds()); 342 profile.profile_duration.InMilliseconds());
333 proto_profile->set_sampling_period_ms( 343 proto_profile->set_sampling_period_ms(
334 profile.sampling_period.InMilliseconds()); 344 profile.sampling_period.InMilliseconds());
Alexei Svitkine (slow) 2017/06/20 20:57:39 Note: I need to double check whether sampling peri
Mike Wittman 2017/06/21 14:49:06 The sampling period is being set correctly, but th
Alexei Svitkine (slow) 2017/06/29 20:51:04 Done.
335 } 345 }
336 346
337 // Translates CallStackProfileParams's process to the corresponding 347 // Translates CallStackProfileParams's process to the corresponding
338 // execution context Process. 348 // execution context Process.
339 Process ToExecutionContextProcess(CallStackProfileParams::Process process) { 349 Process ToExecutionContextProcess(CallStackProfileParams::Process process) {
340 switch (process) { 350 switch (process) {
341 case CallStackProfileParams::UNKNOWN_PROCESS: 351 case CallStackProfileParams::UNKNOWN_PROCESS:
342 return UNKNOWN_PROCESS; 352 return UNKNOWN_PROCESS;
343 case CallStackProfileParams::BROWSER_PROCESS: 353 case CallStackProfileParams::BROWSER_PROCESS:
344 return BROWSER_PROCESS; 354 return BROWSER_PROCESS;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 CallStackProfileParams::Trigger trigger) { 408 CallStackProfileParams::Trigger trigger) {
399 switch (trigger) { 409 switch (trigger) {
400 case CallStackProfileParams::UNKNOWN: 410 case CallStackProfileParams::UNKNOWN:
401 return SampledProfile::UNKNOWN_TRIGGER_EVENT; 411 return SampledProfile::UNKNOWN_TRIGGER_EVENT;
402 case CallStackProfileParams::PROCESS_STARTUP: 412 case CallStackProfileParams::PROCESS_STARTUP:
403 return SampledProfile::PROCESS_STARTUP; 413 return SampledProfile::PROCESS_STARTUP;
404 case CallStackProfileParams::JANKY_TASK: 414 case CallStackProfileParams::JANKY_TASK:
405 return SampledProfile::JANKY_TASK; 415 return SampledProfile::JANKY_TASK;
406 case CallStackProfileParams::THREAD_HUNG: 416 case CallStackProfileParams::THREAD_HUNG:
407 return SampledProfile::THREAD_HUNG; 417 return SampledProfile::THREAD_HUNG;
418 case CallStackProfileParams::PERIODIC_COLLECTION:
419 return SampledProfile::PERIODIC_COLLECTION;
408 } 420 }
409 NOTREACHED(); 421 NOTREACHED();
410 return SampledProfile::UNKNOWN_TRIGGER_EVENT; 422 return SampledProfile::UNKNOWN_TRIGGER_EVENT;
411 } 423 }
412 424
413 } // namespace 425 } // namespace
414 426
415 // CallStackProfileMetricsProvider -------------------------------------------- 427 // CallStackProfileMetricsProvider --------------------------------------------
416 428
417 const char CallStackProfileMetricsProvider::kFieldTrialName[] = 429 const base::Feature CallStackProfileMetricsProvider::kEnableReporting = {
418 "StackProfiling"; 430 "SamplingProfilerReporting", base::FEATURE_DISABLED_BY_DEFAULT};
419 const char CallStackProfileMetricsProvider::kReportProfilesGroupName[] =
420 "Report profiles";
421 431
422 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() { 432 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() {
423 } 433 }
424 434
425 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() { 435 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() {
426 } 436 }
427 437
428 // This function can be invoked on an abitrary thread. 438 // This function can be invoked on an abitrary thread.
429 StackSamplingProfiler::CompletedCallback 439 StackSamplingProfiler::CompletedCallback
430 CallStackProfileMetricsProvider::GetProfilerCallback( 440 CallStackProfileMetricsProvider::GetProfilerCallback(
431 const CallStackProfileParams& params) { 441 CallStackProfileParams* params) {
432 // Ignore the profiles if the collection is disabled. If the collection state 442 // Ignore the profiles if the collection is disabled. If the collection state
433 // changes while collecting, this will be detected by the callback and 443 // changes while collecting, this will be detected by the callback and
434 // profiles will be ignored at that point. 444 // profiles will be ignored at that point.
435 if (!PendingProfiles::GetInstance()->IsCollectionEnabled()) 445 if (!PendingProfiles::GetInstance()->IsCollectionEnabled())
436 return base::Bind(&IgnoreCompletedProfiles); 446 return base::Bind(&IgnoreCompletedProfiles);
437 447
438 return base::Bind(&ReceiveCompletedProfilesImpl, params, 448 params->start_timestamp = base::TimeTicks::Now();
439 base::TimeTicks::Now()); 449 return base::Bind(&ReceiveCompletedProfilesImpl, params);
440 } 450 }
441 451
442 // static 452 // static
443 void CallStackProfileMetricsProvider::ReceiveCompletedProfiles( 453 void CallStackProfileMetricsProvider::ReceiveCompletedProfiles(
444 const CallStackProfileParams& params, 454 CallStackProfileParams* params,
445 base::TimeTicks start_timestamp, 455 base::StackSamplingProfiler::CallStackProfiles profiles) {
446 StackSamplingProfiler::CallStackProfiles profiles) { 456 ReceiveCompletedProfilesImpl(params, std::move(profiles), nullptr);
447 ReceiveCompletedProfilesImpl(params, start_timestamp, std::move(profiles)); 457 }
458
459 // static
460 bool CallStackProfileMetricsProvider::IsPeriodicSamplingEnabled() {
461 return base::GetFieldTrialParamByFeatureAsBool(kEnableReporting, "periodic",
462 false);
448 } 463 }
449 464
450 void CallStackProfileMetricsProvider::OnRecordingEnabled() { 465 void CallStackProfileMetricsProvider::OnRecordingEnabled() {
451 PendingProfiles::GetInstance()->SetCollectionEnabled(true); 466 PendingProfiles::GetInstance()->SetCollectionEnabled(true);
452 } 467 }
453 468
454 void CallStackProfileMetricsProvider::OnRecordingDisabled() { 469 void CallStackProfileMetricsProvider::OnRecordingDisabled() {
455 PendingProfiles::GetInstance()->SetCollectionEnabled(false); 470 PendingProfiles::GetInstance()->SetCollectionEnabled(false);
456 } 471 }
457 472
458 void CallStackProfileMetricsProvider::ProvideGeneralMetrics( 473 void CallStackProfileMetricsProvider::ProvideGeneralMetrics(
459 ChromeUserMetricsExtension* uma_proto) { 474 ChromeUserMetricsExtension* uma_proto) {
460 std::vector<ProfilesState> pending_profiles; 475 std::vector<ProfilesState> pending_profiles;
461 PendingProfiles::GetInstance()->Swap(&pending_profiles); 476 PendingProfiles::GetInstance()->Swap(&pending_profiles);
462 477
463 DCHECK(IsReportingEnabledByFieldTrial() || pending_profiles.empty()); 478 DCHECK(IsReportingEnabledByFieldTrial() || pending_profiles.empty());
464 479
465 for (const ProfilesState& profiles_state : pending_profiles) { 480 for (const ProfilesState& profiles_state : pending_profiles) {
466 for (const StackSamplingProfiler::CallStackProfile& profile : 481 for (const StackSamplingProfiler::CallStackProfile& profile :
467 profiles_state.profiles) { 482 profiles_state.profiles) {
468 SampledProfile* sampled_profile = uma_proto->add_sampled_profile(); 483 SampledProfile* sampled_profile = uma_proto->add_sampled_profile();
469 sampled_profile->set_process(ToExecutionContextProcess( 484 sampled_profile->set_process(
470 profiles_state.params.process)); 485 ToExecutionContextProcess(profiles_state.params.process));
471 sampled_profile->set_thread(ToExecutionContextThread( 486 sampled_profile->set_thread(
472 profiles_state.params.thread)); 487 ToExecutionContextThread(profiles_state.params.thread));
473 sampled_profile->set_trigger_event(ToSampledProfileTriggerEvent( 488 sampled_profile->set_trigger_event(
474 profiles_state.params.trigger)); 489 ToSampledProfileTriggerEvent(profiles_state.params.trigger));
475 CopyProfileToProto(profile, profiles_state.params.ordering_spec, 490 CopyProfileToProto(profile, profiles_state.params.ordering_spec,
476 sampled_profile->mutable_call_stack_profile()); 491 sampled_profile->mutable_call_stack_profile());
477 } 492 }
478 } 493 }
479 } 494 }
480 495
481 // static 496 // static
482 void CallStackProfileMetricsProvider::ResetStaticStateForTesting() { 497 void CallStackProfileMetricsProvider::ResetStaticStateForTesting() {
483 PendingProfiles::GetInstance()->ResetToDefaultStateForTesting(); 498 PendingProfiles::GetInstance()->ResetToDefaultStateForTesting();
484 } 499 }
485 500
486 // static 501 // static
487 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { 502 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() {
488 const std::string group_name = base::FieldTrialList::FindFullName( 503 return base::FeatureList::IsEnabled(kEnableReporting);
489 CallStackProfileMetricsProvider::kFieldTrialName);
490 return group_name ==
491 CallStackProfileMetricsProvider::kReportProfilesGroupName;
492 } 504 }
493 505
494 } // namespace metrics 506 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698