| Index: base/profiler/stack_sampling_profiler.cc
|
| diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
|
| deleted file mode 100644
|
| index 9da662859fd9535cb4037d1d1302401b2566f5b3..0000000000000000000000000000000000000000
|
| --- a/base/profiler/stack_sampling_profiler.cc
|
| +++ /dev/null
|
| @@ -1,311 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "base/profiler/stack_sampling_profiler.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/callback.h"
|
| -#include "base/memory/singleton.h"
|
| -#include "base/profiler/native_stack_sampler.h"
|
| -#include "base/synchronization/lock.h"
|
| -#include "base/timer/elapsed_timer.h"
|
| -
|
| -namespace base {
|
| -
|
| -// DefaultProfileProcessor ----------------------------------------------------
|
| -
|
| -namespace {
|
| -
|
| -// 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:
|
| - using CompletedCallback = StackSamplingProfiler::CompletedCallback;
|
| -
|
| - ~DefaultProfileProcessor();
|
| -
|
| - 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 StackSamplingProfiler::CallStackProfiles& profiles);
|
| -
|
| - private:
|
| - friend struct DefaultSingletonTraits<DefaultProfileProcessor>;
|
| -
|
| - DefaultProfileProcessor();
|
| -
|
| - // Copies the pending profiles from |profiles_| into |profiles|, and clears
|
| - // |profiles_|. This function may be called on any thread.
|
| - void GetAndClearPendingProfiles(
|
| - StackSamplingProfiler::CallStackProfiles* profiles);
|
| -
|
| - // Gets the current completed callback, with proper locking.
|
| - CompletedCallback GetCompletedCallback() const;
|
| -
|
| - mutable Lock callback_lock_;
|
| - CompletedCallback default_completed_callback_;
|
| -
|
| - Lock profiles_lock_;
|
| - StackSamplingProfiler::CallStackProfiles profiles_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor);
|
| -};
|
| -
|
| -DefaultProfileProcessor::~DefaultProfileProcessor() {}
|
| -
|
| -// static
|
| -DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() {
|
| - return Singleton<DefaultProfileProcessor>::get();
|
| -}
|
| -
|
| -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.
|
| - StackSamplingProfiler::CallStackProfiles profiles;
|
| - GetAndClearPendingProfiles(&profiles);
|
| - if (!profiles.empty())
|
| - callback.Run(profiles);
|
| - }
|
| -}
|
| -
|
| -void DefaultProfileProcessor::ProcessProfiles(
|
| - const StackSamplingProfiler::CallStackProfiles& profiles) {
|
| - 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());
|
| - }
|
| -}
|
| -
|
| -DefaultProfileProcessor::DefaultProfileProcessor() {}
|
| -
|
| -void DefaultProfileProcessor::GetAndClearPendingProfiles(
|
| - StackSamplingProfiler::CallStackProfiles* 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 ----------------------------------------------
|
| -
|
| -StackSamplingProfiler::Module::Module() : base_address(nullptr) {}
|
| -StackSamplingProfiler::Module::Module(const void* base_address,
|
| - const std::string& id,
|
| - const FilePath& filename)
|
| - : base_address(base_address), id(id), filename(filename) {}
|
| -
|
| -StackSamplingProfiler::Module::~Module() {}
|
| -
|
| -// StackSamplingProfiler::Frame -----------------------------------------------
|
| -
|
| -StackSamplingProfiler::Frame::Frame(const void* instruction_pointer,
|
| - size_t module_index)
|
| - : instruction_pointer(instruction_pointer),
|
| - module_index(module_index) {}
|
| -
|
| -StackSamplingProfiler::Frame::~Frame() {}
|
| -
|
| -// StackSamplingProfiler::CallStackProfile ------------------------------------
|
| -
|
| -StackSamplingProfiler::CallStackProfile::CallStackProfile()
|
| - : preserve_sample_ordering(false), user_data(0) {}
|
| -
|
| -StackSamplingProfiler::CallStackProfile::~CallStackProfile() {}
|
| -
|
| -// StackSamplingProfiler::SamplingThread --------------------------------------
|
| -
|
| -StackSamplingProfiler::SamplingThread::SamplingThread(
|
| - scoped_ptr<NativeStackSampler> native_sampler,
|
| - const SamplingParams& params,
|
| - CompletedCallback completed_callback)
|
| - : native_sampler_(native_sampler.Pass()),
|
| - params_(params),
|
| - stop_event_(false, false),
|
| - completed_callback_(completed_callback) {
|
| -}
|
| -
|
| -StackSamplingProfiler::SamplingThread::~SamplingThread() {}
|
| -
|
| -void StackSamplingProfiler::SamplingThread::ThreadMain() {
|
| - PlatformThread::SetName("Chrome_SamplingProfilerThread");
|
| -
|
| - CallStackProfiles profiles;
|
| - CollectProfiles(&profiles);
|
| - completed_callback_.Run(profiles);
|
| -}
|
| -
|
| -// Depending on how long the sampling takes and the length of the sampling
|
| -// interval, a burst of samples could take arbitrarily longer than
|
| -// samples_per_burst * sampling_interval. In this case, we (somewhat
|
| -// arbitrarily) honor the number of samples requested rather than strictly
|
| -// adhering to the sampling intervals. Once we have established users for the
|
| -// StackSamplingProfiler and the collected data to judge, we may go the other
|
| -// way or make this behavior configurable.
|
| -bool StackSamplingProfiler::SamplingThread::CollectProfile(
|
| - CallStackProfile* profile,
|
| - TimeDelta* elapsed_time) {
|
| - ElapsedTimer profile_timer;
|
| - CallStackProfile current_profile;
|
| - native_sampler_->ProfileRecordingStarting(¤t_profile.modules);
|
| - current_profile.sampling_period = params_.sampling_interval;
|
| - bool burst_completed = true;
|
| - TimeDelta previous_elapsed_sample_time;
|
| - for (int i = 0; i < params_.samples_per_burst; ++i) {
|
| - if (i != 0) {
|
| - // Always wait, even if for 0 seconds, so we can observe a signal on
|
| - // stop_event_.
|
| - if (stop_event_.TimedWait(
|
| - std::max(params_.sampling_interval - previous_elapsed_sample_time,
|
| - TimeDelta()))) {
|
| - burst_completed = false;
|
| - break;
|
| - }
|
| - }
|
| - ElapsedTimer sample_timer;
|
| - current_profile.samples.push_back(Sample());
|
| - native_sampler_->RecordStackSample(¤t_profile.samples.back());
|
| - previous_elapsed_sample_time = sample_timer.Elapsed();
|
| - }
|
| -
|
| - *elapsed_time = profile_timer.Elapsed();
|
| - current_profile.profile_duration = *elapsed_time;
|
| - current_profile.preserve_sample_ordering = params_.preserve_sample_ordering;
|
| - current_profile.user_data = params_.user_data;
|
| - native_sampler_->ProfileRecordingStopped();
|
| -
|
| - if (burst_completed)
|
| - *profile = current_profile;
|
| -
|
| - return burst_completed;
|
| -}
|
| -
|
| -// In an analogous manner to CollectProfile() and samples exceeding the expected
|
| -// total sampling time, bursts may also exceed the burst_interval. We adopt the
|
| -// same wait-and-see approach here.
|
| -void StackSamplingProfiler::SamplingThread::CollectProfiles(
|
| - CallStackProfiles* profiles) {
|
| - if (stop_event_.TimedWait(params_.initial_delay))
|
| - return;
|
| -
|
| - TimeDelta previous_elapsed_profile_time;
|
| - for (int i = 0; i < params_.bursts; ++i) {
|
| - if (i != 0) {
|
| - // Always wait, even if for 0 seconds, so we can observe a signal on
|
| - // stop_event_.
|
| - if (stop_event_.TimedWait(
|
| - std::max(params_.burst_interval - previous_elapsed_profile_time,
|
| - TimeDelta())))
|
| - return;
|
| - }
|
| -
|
| - CallStackProfile profile;
|
| - if (!CollectProfile(&profile, &previous_elapsed_profile_time))
|
| - return;
|
| - profiles->push_back(profile);
|
| - }
|
| -}
|
| -
|
| -void StackSamplingProfiler::SamplingThread::Stop() {
|
| - stop_event_.Signal();
|
| -}
|
| -
|
| -// StackSamplingProfiler ------------------------------------------------------
|
| -
|
| -StackSamplingProfiler::SamplingParams::SamplingParams()
|
| - : initial_delay(TimeDelta::FromMilliseconds(0)),
|
| - bursts(1),
|
| - burst_interval(TimeDelta::FromMilliseconds(10000)),
|
| - samples_per_burst(300),
|
| - sampling_interval(TimeDelta::FromMilliseconds(100)),
|
| - preserve_sample_ordering(false),
|
| - user_data(0) {
|
| -}
|
| -
|
| -StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
|
| - const SamplingParams& params)
|
| - : thread_id_(thread_id), params_(params) {}
|
| -
|
| -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() {
|
| - 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_, callback));
|
| - if (!PlatformThread::Create(0, sampling_thread_.get(),
|
| - &sampling_thread_handle_))
|
| - sampling_thread_.reset();
|
| -}
|
| -
|
| -void StackSamplingProfiler::Stop() {
|
| - if (sampling_thread_)
|
| - sampling_thread_->Stop();
|
| -}
|
| -
|
| -// static
|
| -void StackSamplingProfiler::SetDefaultCompletedCallback(
|
| - CompletedCallback callback) {
|
| - DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback);
|
| -}
|
| -
|
| -// StackSamplingProfiler::Frame global functions ------------------------------
|
| -
|
| -bool operator==(const StackSamplingProfiler::Frame &a,
|
| - const StackSamplingProfiler::Frame &b) {
|
| - return a.instruction_pointer == b.instruction_pointer &&
|
| - a.module_index == b.module_index;
|
| -}
|
| -
|
| -bool operator<(const StackSamplingProfiler::Frame &a,
|
| - const StackSamplingProfiler::Frame &b) {
|
| - return (a.module_index < b.module_index) ||
|
| - (a.module_index == b.module_index &&
|
| - a.instruction_pointer < b.instruction_pointer);
|
| -}
|
| -
|
| -} // namespace base
|
|
|