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

Unified Diff: base/profiler/stack_sampling_profiler.cc

Issue 1029653002: Enable startup profiling by Win x64 stack sampling profiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@statprof-metrics-provider
Patch Set: early destruction fix Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: base/profiler/stack_sampling_profiler.cc
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index f7605079953769e162aa7463ebc54c6ea772485a..86347a7f1ddc26aa9c1315e8ee958530d0edb339 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -19,49 +19,94 @@ namespace base {
namespace {
-// Thread-safe singleton class that stores collected profiles waiting to be
-// processed.
-class PendingProfiles {
+// Singleton class responsible for providing the default processing for profiles
+// (i.e. for profiles generated by profilers without their own completed
+// callback).
+class DefaultProfileProcessor {
public:
- PendingProfiles();
- ~PendingProfiles();
+ using CompletedCallback = StackSamplingProfiler::CompletedCallback;
- static PendingProfiles* GetInstance();
+ DefaultProfileProcessor();
+ ~DefaultProfileProcessor();
- // Appends |profiles|. This function is thread safe.
- void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles);
- // Gets the pending profiles into *|profiles|. This function is thread safe.
- void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles);
+ static DefaultProfileProcessor* GetInstance();
+
+ // Sets the callback to use for processing profiles captured without a
+ // per-profiler completed callback. Pending completed profiles are stored in
+ // this object until a non-null callback is provided here. This function is
+ // thread-safe.
+ void SetCompletedCallback(CompletedCallback callback);
+
+ // Processes |profiles|. This function is thread safe.
+ void ProcessProfiles(
+ const std::vector<StackSamplingProfiler::Profile>& profiles);
private:
+ // Gets the pending profiles into *|profiles|, with proper locking.
+ void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles);
+
+ // Gets the current completed callback, with proper locking.
+ CompletedCallback GetCompletedCallback() const;
+
+ mutable Lock callback_lock_;
+ CompletedCallback default_completed_callback_;
+
Lock profiles_lock_;
std::vector<StackSamplingProfiler::Profile> profiles_;
- DISALLOW_COPY_AND_ASSIGN(PendingProfiles);
+ DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor);
};
-PendingProfiles::PendingProfiles() {}
+DefaultProfileProcessor::DefaultProfileProcessor() {}
-PendingProfiles::~PendingProfiles() {}
+DefaultProfileProcessor::~DefaultProfileProcessor() {}
// static
-PendingProfiles* PendingProfiles::GetInstance() {
- return Singleton<PendingProfiles>::get();
+DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() {
+ return Singleton<DefaultProfileProcessor>::get();
}
-void PendingProfiles::PutProfiles(
+void DefaultProfileProcessor::SetCompletedCallback(CompletedCallback callback) {
+ {
+ AutoLock scoped_lock(callback_lock_);
+ default_completed_callback_ = callback;
+ }
+
+ if (!callback.is_null()) {
+ // Provide any pending profiles to the callback immediately.
+ std::vector<StackSamplingProfiler::Profile> profiles;
+ GetProfiles(&profiles);
+ if (!profiles.empty())
+ callback.Run(profiles);
+ }
+}
+
+void DefaultProfileProcessor::ProcessProfiles(
const std::vector<StackSamplingProfiler::Profile>& profiles) {
- AutoLock scoped_lock(profiles_lock_);
- profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
+ CompletedCallback callback = GetCompletedCallback();
+
+ // Store pending profiles if we don't have a valid callback.
+ if (!callback.is_null()) {
+ callback.Run(profiles);
+ } else {
+ AutoLock scoped_lock(profiles_lock_);
+ profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
+ }
}
-void PendingProfiles::GetProfiles(
+void DefaultProfileProcessor::GetProfiles(
std::vector<StackSamplingProfiler::Profile>* profiles) {
profiles->clear();
AutoLock scoped_lock(profiles_lock_);
profiles_.swap(*profiles);
}
+
+DefaultProfileProcessor::CompletedCallback
+DefaultProfileProcessor::GetCompletedCallback() const {
+ AutoLock scoped_lock(callback_lock_);
+ return default_completed_callback_;
+}
} // namespace
StackSamplingProfiler::Module::Module() : base_address(nullptr) {}
@@ -90,12 +135,11 @@ StackSamplingProfiler::Profile::~Profile() {}
class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
public:
// Samples stacks using |native_sampler|. When complete, invokes
- // |profiles_callback| with the collected profiles. |profiles_callback| must
- // be thread-safe and may consume the contents of the vector.
- SamplingThread(
- scoped_ptr<NativeStackSampler> native_sampler,
- const SamplingParams& params,
- Callback<void(const std::vector<Profile>&)> completed_callback);
+ // |completed_callback| with the collected profiles. |completed_callback| must
+ // be thread-safe.
+ SamplingThread(scoped_ptr<NativeStackSampler> native_sampler,
+ const SamplingParams& params,
+ CompletedCallback completed_callback);
~SamplingThread() override;
// Implementation of PlatformThread::Delegate:
@@ -108,7 +152,7 @@ class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
// collected, or false if collection was stopped before it completed.
bool CollectProfile(Profile* profile, TimeDelta* elapsed_time);
// Collects profiles from all bursts, or until the sampling is stopped. If
- // stopped before complete, |profiles| will contains only full bursts.
+ // stopped before complete, |profiles| will contain only full bursts.
void CollectProfiles(std::vector<Profile>* profiles);
scoped_ptr<NativeStackSampler> native_sampler_;
@@ -117,7 +161,7 @@ class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
WaitableEvent stop_event_;
- Callback<void(const std::vector<Profile>&)> completed_callback_;
+ CompletedCallback completed_callback_;
DISALLOW_COPY_AND_ASSIGN(SamplingThread);
};
@@ -125,7 +169,7 @@ class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate {
StackSamplingProfiler::SamplingThread::SamplingThread(
scoped_ptr<NativeStackSampler> native_sampler,
const SamplingParams& params,
- Callback<void(const std::vector<Profile>&)> completed_callback)
+ CompletedCallback completed_callback)
: native_sampler_(native_sampler.Pass()),
params_(params),
stop_event_(false, false),
@@ -221,21 +265,32 @@ StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
const SamplingParams& params)
: thread_id_(thread_id), params_(params) {}
-StackSamplingProfiler::~StackSamplingProfiler() {}
+StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
+ const SamplingParams& params,
+ CompletedCallback callback)
+ : thread_id_(thread_id), params_(params), completed_callback_(callback) {}
+
+StackSamplingProfiler::~StackSamplingProfiler() {
+ Stop();
+ if (!sampling_thread_handle_.is_null())
+ PlatformThread::Join(sampling_thread_handle_);
+}
void StackSamplingProfiler::Start() {
- native_sampler_ = NativeStackSampler::Create(thread_id_);
- if (!native_sampler_)
+ scoped_ptr<NativeStackSampler> native_sampler(
+ NativeStackSampler::Create(thread_id_));
+ if (!native_sampler)
return;
+ CompletedCallback callback =
+ !completed_callback_.is_null() ? completed_callback_ :
+ Bind(&DefaultProfileProcessor::ProcessProfiles,
+ Unretained(DefaultProfileProcessor::GetInstance()));
+
sampling_thread_.reset(
- new SamplingThread(
- native_sampler_.Pass(), params_,
- (custom_completed_callback_.is_null() ?
- Bind(&PendingProfiles::PutProfiles,
- Unretained(PendingProfiles::GetInstance())) :
- custom_completed_callback_)));
- if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get()))
+ new SamplingThread(native_sampler.Pass(), params_, callback));
+ if (!PlatformThread::Create(0, sampling_thread_.get(),
+ &sampling_thread_handle_))
LOG(ERROR) << "failed to create thread";
}
@@ -245,13 +300,9 @@ void StackSamplingProfiler::Stop() {
}
// static
-void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) {
- PendingProfiles::GetInstance()->GetProfiles(profiles);
-}
-
-void StackSamplingProfiler::SetCustomCompletedCallback(
- Callback<void(const std::vector<Profile>&)> callback) {
- custom_completed_callback_ = callback;
+void StackSamplingProfiler::SetDefaultCompletedCallback(
+ CompletedCallback callback) {
+ DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback);
}
bool operator==(const StackSamplingProfiler::Frame &a,

Powered by Google App Engine
This is Rietveld 408576698