Commit 000c8944 authored by Xi Cheng's avatar Xi Cheng Committed by Commit Bot

Introduce StackProfileBuilder to generate a CallStackProfile

This CL introduces a new class StackProfileBuilder owned by StackSamplingProfiler.

This CL also refactors both Windows and Mac profile construction into the
StackProfileBuilder class to generate a StackSamplingProfiler::CallStackProfile.

Bug: 851163
Change-Id: I6acde44fc1e38ae04d1d747fe2d3843faba3a218
Reviewed-on: https://chromium-review.googlesource.com/1101462Reviewed-by: default avatarMike Wittman <wittman@chromium.org>
Commit-Queue: Xi Cheng <chengx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568239}
parent c47cb2d9
......@@ -17,8 +17,8 @@ namespace base {
class NativeStackSamplerTestDelegate;
// NativeStackSampler is an implementation detail of StackSamplingProfiler. It
// abstracts the native implementation required to record a stack sample for a
// given thread.
// abstracts the native implementation required to record a set of stack frames
// for a given thread.
class NativeStackSampler {
public:
// This class contains a buffer for stack copies that can be shared across
......@@ -41,22 +41,12 @@ class NativeStackSampler {
DISALLOW_COPY_AND_ASSIGN(StackBuffer);
};
// The callback type used to add annotations to a sample during collection.
// This is passed to the native sampler to be applied at the most appropriate
// time. It is a simple function-pointer because the generated code must be
// completely predictable and do nothing that could acquire a mutex; a
// Callback object is code outside the control of this object and could,
// for example, acquire a mutex as part of allocating memory for a LOG
// message.
using AnnotateCallback = void (*)(StackSamplingProfiler::Sample*);
virtual ~NativeStackSampler();
// Creates a stack sampler that records samples for thread with |thread_id|.
// Returns null if this platform does not support stack sampling.
static std::unique_ptr<NativeStackSampler> Create(
PlatformThreadId thread_id,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate);
// Gets the required size of the stack buffer.
......@@ -74,9 +64,10 @@ class NativeStackSampler {
virtual void ProfileRecordingStarting(
std::vector<StackSamplingProfiler::Module>* modules) = 0;
// Records a stack sample to |sample|.
virtual void RecordStackSample(StackBuffer* stackbuffer,
StackSamplingProfiler::Sample* sample) = 0;
// Records a set of stack frames and returns them.
virtual std::vector<StackSamplingProfiler::Frame> RecordStackFrames(
StackBuffer* stackbuffer,
StackSamplingProfiler::SamplingProfileBuilder* profile_builder) = 0;
// Notifies the sampler that we've stopped recording the current profile.
virtual void ProfileRecordingStopped() = 0;
......
......@@ -468,28 +468,29 @@ class ScopedSuspendThread {
class NativeStackSamplerMac : public NativeStackSampler {
public:
NativeStackSamplerMac(mach_port_t thread_port,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate);
~NativeStackSamplerMac() override;
// StackSamplingProfiler::NativeStackSampler:
void ProfileRecordingStarting(
std::vector<StackSamplingProfiler::Module>* modules) override;
void RecordStackSample(StackBuffer* stack_buffer,
StackSamplingProfiler::Sample* sample) override;
std::vector<StackSamplingProfiler::Frame> RecordStackFrames(
StackBuffer* stack_buffer,
StackSamplingProfiler::SamplingProfileBuilder* profile_builder) override;
void ProfileRecordingStopped() override;
private:
// Suspends the thread with |thread_port_|, copies its stack and resumes the
// thread, then records the stack frames and associated modules into |sample|.
void SuspendThreadAndRecordStack(StackBuffer* stack_buffer,
StackSamplingProfiler::Sample* sample);
// thread.
// Returns a vector of frames which record the information of the stack frames
// and associated modules.
std::vector<StackSamplingProfiler::Frame> SuspendThreadAndRecordStack(
StackBuffer* stack_buffer,
StackSamplingProfiler::SamplingProfileBuilder* profile_builder);
// Weak reference: Mach port for thread being profiled.
mach_port_t thread_port_;
const AnnotateCallback annotator_;
NativeStackSamplerTestDelegate* const test_delegate_;
// The stack base address corresponding to |thread_handle_|.
......@@ -512,15 +513,11 @@ class NativeStackSamplerMac : public NativeStackSampler {
NativeStackSamplerMac::NativeStackSamplerMac(
mach_port_t thread_port,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate)
: thread_port_(thread_port),
annotator_(annotator),
test_delegate_(test_delegate),
thread_stack_base_address_(
pthread_get_stackaddr_np(pthread_from_mach_thread_np(thread_port))) {
DCHECK(annotator_);
GetSigtrampRange(&sigtramp_start_, &sigtramp_end_);
// This class suspends threads, and those threads might be suspended in dyld.
// Therefore, for all the system functions that might be linked in dynamically
......@@ -538,23 +535,27 @@ void NativeStackSamplerMac::ProfileRecordingStarting(
profile_module_index_.clear();
}
void NativeStackSamplerMac::RecordStackSample(
std::vector<StackSamplingProfiler::Frame>
NativeStackSamplerMac::RecordStackFrames(
StackBuffer* stack_buffer,
StackSamplingProfiler::Sample* sample) {
StackSamplingProfiler::SamplingProfileBuilder* profile_builder) {
DCHECK(current_modules_);
SuspendThreadAndRecordStack(stack_buffer, sample);
return SuspendThreadAndRecordStack(stack_buffer, profile_builder);
}
void NativeStackSamplerMac::ProfileRecordingStopped() {
current_modules_ = nullptr;
}
void NativeStackSamplerMac::SuspendThreadAndRecordStack(
std::vector<StackSamplingProfiler::Frame>
NativeStackSamplerMac::SuspendThreadAndRecordStack(
StackBuffer* stack_buffer,
StackSamplingProfiler::Sample* sample) {
StackSamplingProfiler::SamplingProfileBuilder* profile_builder) {
x86_thread_state64_t thread_state;
std::vector<StackSamplingProfiler::Frame> frames;
// Copy the stack.
uintptr_t new_stack_top = 0;
......@@ -565,20 +566,21 @@ void NativeStackSamplerMac::SuspendThreadAndRecordStack(
// default heap acquired by the target thread before it was suspended.
ScopedSuspendThread suspend_thread(thread_port_);
if (!suspend_thread.was_successful())
return;
return frames;
if (!GetThreadState(thread_port_, &thread_state))
return;
return frames;
auto stack_top = reinterpret_cast<uintptr_t>(thread_stack_base_address_);
uintptr_t stack_bottom = thread_state.__rsp;
if (stack_bottom >= stack_top)
return;
uintptr_t stack_size = stack_top - stack_bottom;
return frames;
uintptr_t stack_size = stack_top - stack_bottom;
if (stack_size > stack_buffer->size())
return;
return frames;
(*annotator_)(sample);
profile_builder->RecordAnnotations();
CopyStackAndRewritePointers(
reinterpret_cast<uintptr_t*>(stack_buffer->buffer()),
......@@ -596,7 +598,7 @@ void NativeStackSamplerMac::SuspendThreadAndRecordStack(
// Reserve enough memory for most stacks, to avoid repeated allocations.
// Approximately 99.9% of recorded stacks are 128 frames or fewer.
sample->frames.reserve(128);
frames.reserve(128);
auto* current_modules = current_modules_;
auto* profile_module_index = &profile_module_index_;
......@@ -606,9 +608,9 @@ void NativeStackSamplerMac::SuspendThreadAndRecordStack(
// and bail. See MayTriggerUnwInitLocalCrash for details.
uintptr_t rip = thread_state.__rip;
if (MayTriggerUnwInitLocalCrash(rip)) {
sample->frames.emplace_back(
frames.emplace_back(
rip, GetModuleIndex(rip, current_modules, profile_module_index));
return;
return frames;
}
const auto continue_predicate = [this,
......@@ -628,21 +630,21 @@ void NativeStackSamplerMac::SuspendThreadAndRecordStack(
};
WalkStack(thread_state, current_modules, profile_module_index,
[sample, current_modules, profile_module_index](
[&frames, current_modules, profile_module_index](
uintptr_t frame_ip, size_t module_index) {
sample->frames.emplace_back(frame_ip, module_index);
frames.emplace_back(frame_ip, module_index);
},
continue_predicate);
return frames;
}
} // namespace
std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
PlatformThreadId thread_id,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate) {
return std::make_unique<NativeStackSamplerMac>(thread_id, annotator,
test_delegate);
return std::make_unique<NativeStackSamplerMac>(thread_id, test_delegate);
}
size_t NativeStackSampler::GetStackBufferSize() {
......
......@@ -8,7 +8,6 @@ namespace base {
std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
PlatformThreadId thread_id,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate) {
return std::unique_ptr<NativeStackSampler>();
}
......
......@@ -334,8 +334,7 @@ void SuspendThreadAndRecordStack(
void* stack_copy_buffer,
size_t stack_copy_buffer_size,
std::vector<RecordedFrame>* stack,
NativeStackSampler::AnnotateCallback annotator,
StackSamplingProfiler::Sample* sample,
StackSamplingProfiler::SamplingProfileBuilder* profile_builder,
NativeStackSamplerTestDelegate* test_delegate) {
DCHECK(stack->empty());
......@@ -370,7 +369,7 @@ void SuspendThreadAndRecordStack(
if (PointsToGuardPage(bottom))
return;
(*annotator)(sample);
profile_builder->RecordAnnotations();
CopyMemoryFromStack(stack_copy_buffer,
reinterpret_cast<const void*>(bottom), top - bottom);
......@@ -389,15 +388,15 @@ void SuspendThreadAndRecordStack(
class NativeStackSamplerWin : public NativeStackSampler {
public:
NativeStackSamplerWin(win::ScopedHandle thread_handle,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate);
~NativeStackSamplerWin() override;
// StackSamplingProfiler::NativeStackSampler:
void ProfileRecordingStarting(
std::vector<StackSamplingProfiler::Module>* modules) override;
void RecordStackSample(StackBuffer* stack_buffer,
StackSamplingProfiler::Sample* sample) override;
std::vector<StackSamplingProfiler::Frame> RecordStackFrames(
StackBuffer* stack_buffer,
StackSamplingProfiler::SamplingProfileBuilder* profile_builder) override;
void ProfileRecordingStopped() override;
private:
......@@ -413,15 +412,14 @@ class NativeStackSamplerWin : public NativeStackSampler {
size_t GetModuleIndex(HMODULE module_handle,
std::vector<StackSamplingProfiler::Module>* modules);
// Copies the information represented by |stack| into |sample| and |modules|.
void CopyToSample(const std::vector<RecordedFrame>& stack,
StackSamplingProfiler::Sample* sample,
std::vector<StackSamplingProfiler::Module>* modules);
// Creates a set of frames with the information represented by |stack| and
// |modules|.
std::vector<StackSamplingProfiler::Frame> CreateFrames(
const std::vector<RecordedFrame>& stack,
std::vector<StackSamplingProfiler::Module>* modules);
win::ScopedHandle thread_handle_;
const AnnotateCallback annotator_;
NativeStackSamplerTestDelegate* const test_delegate_;
// The stack base address corresponding to |thread_handle_|.
......@@ -440,15 +438,11 @@ class NativeStackSamplerWin : public NativeStackSampler {
NativeStackSamplerWin::NativeStackSamplerWin(
win::ScopedHandle thread_handle,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate)
: thread_handle_(thread_handle.Take()),
annotator_(annotator),
test_delegate_(test_delegate),
thread_stack_base_address_(
GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase) {
DCHECK(annotator_);
}
GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase) {}
NativeStackSamplerWin::~NativeStackSamplerWin() {
}
......@@ -459,17 +453,19 @@ void NativeStackSamplerWin::ProfileRecordingStarting(
profile_module_index_.clear();
}
void NativeStackSamplerWin::RecordStackSample(
std::vector<StackSamplingProfiler::Frame>
NativeStackSamplerWin::RecordStackFrames(
StackBuffer* stack_buffer,
StackSamplingProfiler::Sample* sample) {
StackSamplingProfiler::SamplingProfileBuilder* profile_builder) {
DCHECK(stack_buffer);
DCHECK(current_modules_);
std::vector<RecordedFrame> stack;
SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_,
stack_buffer->buffer(), stack_buffer->size(),
&stack, annotator_, sample, test_delegate_);
CopyToSample(stack, sample, current_modules_);
&stack, profile_builder, test_delegate_);
return CreateFrames(stack, current_modules_);
}
void NativeStackSamplerWin::ProfileRecordingStopped() {
......@@ -511,25 +507,24 @@ size_t NativeStackSamplerWin::GetModuleIndex(
return loc->second;
}
void NativeStackSamplerWin::CopyToSample(
std::vector<StackSamplingProfiler::Frame> NativeStackSamplerWin::CreateFrames(
const std::vector<RecordedFrame>& stack,
StackSamplingProfiler::Sample* sample,
std::vector<StackSamplingProfiler::Module>* modules) {
sample->frames.clear();
sample->frames.reserve(stack.size());
std::vector<StackSamplingProfiler::Frame> frames;
frames.reserve(stack.size());
for (const auto& frame : stack) {
sample->frames.emplace_back(
reinterpret_cast<uintptr_t>(frame.instruction_pointer),
GetModuleIndex(frame.module.Get(), modules));
frames.emplace_back(reinterpret_cast<uintptr_t>(frame.instruction_pointer),
GetModuleIndex(frame.module.Get(), modules));
}
return frames;
}
} // namespace
std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
PlatformThreadId thread_id,
AnnotateCallback annotator,
NativeStackSamplerTestDelegate* test_delegate) {
#if _WIN64
// Get the thread's handle.
......@@ -540,7 +535,7 @@ std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
if (thread_handle) {
return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin(
win::ScopedHandle(thread_handle), annotator, test_delegate));
win::ScopedHandle(thread_handle), test_delegate));
}
#endif
return std::unique_ptr<NativeStackSampler>();
......
......@@ -75,8 +75,7 @@ StackSamplingProfiler::Frame::Frame(uintptr_t instruction_pointer,
StackSamplingProfiler::Frame::~Frame() = default;
StackSamplingProfiler::Frame::Frame()
: instruction_pointer(0), module_index(kUnknownModuleIndex) {
}
: instruction_pointer(0), module_index(kUnknownModuleIndex) {}
// StackSamplingProfiler::Sample ----------------------------------------------
......@@ -114,6 +113,40 @@ StackSamplingProfiler::CallStackProfile::CopyForTesting() const {
StackSamplingProfiler::CallStackProfile::CallStackProfile(
const CallStackProfile& other) = default;
// StackSamplingProfiler::SamplingProfileBuilder ------------------------------
StackSamplingProfiler::SamplingProfileBuilder::SamplingProfileBuilder(
const CompletedCallback& callback)
: callback_(callback) {}
StackSamplingProfiler::SamplingProfileBuilder::~SamplingProfileBuilder() =
default;
void StackSamplingProfiler::SamplingProfileBuilder::RecordAnnotations() {
// The code inside this method must not do anything that could acquire a
// mutex, including allocating memory (which includes LOG messages) because
// that mutex could be held by a stopped thread, thus resulting in deadlock.
sample_.process_milestones = subtle::NoBarrier_Load(&process_milestones_);
}
void StackSamplingProfiler::SamplingProfileBuilder::OnProfileCompleted(
TimeDelta profile_duration,
TimeDelta sampling_period) {
profile_.profile_duration = profile_duration;
profile_.sampling_period = sampling_period;
// Run the associated callback, passing the collected profile.
callback_.Run(std::move(profile_));
}
void StackSamplingProfiler::SamplingProfileBuilder::OnSampleCompleted(
std::vector<Frame> frames) {
DCHECK_EQ(sample_.frames.size(), 0u);
sample_.frames = std::move(frames);
profile_.samples.push_back(std::move(sample_));
sample_ = Sample();
}
// StackSamplingProfiler::SamplingThread --------------------------------------
class StackSamplingProfiler::SamplingThread : public Thread {
......@@ -146,29 +179,31 @@ class StackSamplingProfiler::SamplingThread : public Thread {
struct CollectionContext {
CollectionContext(PlatformThreadId target,
const SamplingParams& params,
const CompletedCallback& callback,
WaitableEvent* finished,
std::unique_ptr<NativeStackSampler> sampler)
std::unique_ptr<NativeStackSampler> sampler,
std::unique_ptr<SamplingProfileBuilder> profile_builder)
: collection_id(next_collection_id.GetNext()),
target(target),
params(params),
callback(callback),
finished(finished),
native_sampler(std::move(sampler)) {}
native_sampler(std::move(sampler)),
profile_builder(std::move(profile_builder)) {}
~CollectionContext() = default;
// An identifier for this collection, used to uniquely identify the
// collection to outside interests.
const int collection_id;
const PlatformThreadId target; // ID of The thread being sampled.
const SamplingParams params; // Information about how to sample.
const CompletedCallback callback; // Callback made when sampling complete.
WaitableEvent* const finished; // Signaled when all sampling complete.
const PlatformThreadId target; // ID of The thread being sampled.
const SamplingParams params; // Information about how to sample.
WaitableEvent* const finished; // Signaled when all sampling complete.
// Platform-specific module that does the actual sampling.
std::unique_ptr<NativeStackSampler> native_sampler;
// Receives the sampling data and builds a CallStackProfile.
std::unique_ptr<SamplingProfileBuilder> profile_builder;
// The absolute time for the next sample.
Time next_sample_time;
......@@ -178,9 +213,6 @@ class StackSamplingProfiler::SamplingThread : public Thread {
// Counter that indicates the current sample position along the acquisition.
int sample_count = 0;
// The collected stack samples.
CallStackProfile profile;
// Sequence number for generating new collection ids.
static AtomicSequenceNumber next_collection_id;
};
......@@ -232,10 +264,10 @@ class StackSamplingProfiler::SamplingThread : public Thread {
// Get task runner that is usable from the sampling thread itself.
scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread();
// Finishes a collection and reports collected data via callback. The
// collection's |finished| waitable event will be signalled. The |collection|
// should already have been removed from |active_collections_| by the caller,
// as this is needed to avoid flakiness in unit tests.
// Finishes a collection. The collection's |finished| waitable event will be
// signalled. The |collection| should already have been removed from
// |active_collections_| by the caller, as this is needed to avoid flakiness
// in unit tests.
void FinishCollection(CollectionContext* collection);
// Check if the sampling thread is idle and begin a shutdown if it is.
......@@ -488,24 +520,16 @@ void StackSamplingProfiler::SamplingThread::FinishCollection(
DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
DCHECK_EQ(0u, active_collections_.count(collection->collection_id));
collection->profile.profile_duration = Time::Now() -
collection->profile_start_time +
collection->params.sampling_interval;
collection->native_sampler->ProfileRecordingStopped();
TimeDelta profile_duration = Time::Now() - collection->profile_start_time +
collection->params.sampling_interval;
// Extract some information so callback and event-signalling can still be
// done after the collection has been removed from the list of "active"
// ones. This allows the the controlling object (and tests using it) to be
// confident that collection is fully finished when those things occur.
const CompletedCallback callback = collection->callback;
CallStackProfile profile = std::move(collection->profile);
WaitableEvent* finished = collection->finished;
collection->native_sampler->ProfileRecordingStopped();
// Run the associated callback, passing the collected profile.
callback.Run(std::move(profile));
collection->profile_builder->OnProfileCompleted(
profile_duration, collection->params.sampling_interval);
// Signal that this collection is finished.
finished->Signal();
collection->finished->Signal();
ScheduleShutdownIfIdle();
}
......@@ -583,19 +607,18 @@ void StackSamplingProfiler::SamplingThread::RecordSampleTask(
CollectionContext* collection = found->second.get();
// If this is the first sample, the profile params need to be filled.
// If this is the first sample, the collection params need to be filled.
if (collection->sample_count == 0) {
collection->profile.sampling_period = collection->params.sampling_interval;
collection->profile_start_time = Time::Now();
collection->next_sample_time = Time::Now();
collection->native_sampler->ProfileRecordingStarting(
&collection->profile.modules);
collection->profile_builder->modules());
}
// Record a single sample.
collection->profile.samples.push_back(Sample());
collection->native_sampler->RecordStackSample(
stack_buffer_.get(), &collection->profile.samples.back());
collection->profile_builder->OnSampleCompleted(
collection->native_sampler->RecordStackFrames(
stack_buffer_.get(), collection->profile_builder.get()));
// Schedule the next sample recording if there is one.
if (++collection->sample_count < collection->params.samples_per_profile) {
......@@ -745,9 +768,10 @@ void StackSamplingProfiler::Start() {
if (completed_callback_.is_null())
return;
profile_builder_.reset(new SamplingProfileBuilder(completed_callback_));
std::unique_ptr<NativeStackSampler> native_sampler =
NativeStackSampler::Create(thread_id_, &RecordAnnotations,
test_delegate_);
NativeStackSampler::Create(thread_id_, test_delegate_);
if (!native_sampler)
return;
......@@ -767,8 +791,8 @@ void StackSamplingProfiler::Start() {
DCHECK_EQ(kNullProfilerId, profiler_id_);
profiler_id_ = SamplingThread::GetInstance()->Add(
std::make_unique<SamplingThread::CollectionContext>(
thread_id_, params_, completed_callback_, &profiling_inactive_,
std::move(native_sampler)));
thread_id_, params_, &profiling_inactive_, std::move(native_sampler),
std::move(profile_builder_)));
DCHECK_NE(kNullProfilerId, profiler_id_);
}
......@@ -785,14 +809,6 @@ void StackSamplingProfiler::SetProcessMilestone(int milestone) {
ChangeAtomicFlags(&process_milestones_, 1 << milestone, 0);
}
// static
void StackSamplingProfiler::RecordAnnotations(Sample* sample) {
// The code inside this method must not do anything that could acquire a
// mutex, including allocating memory (which includes LOG messages) because
// that mutex could be held by a stopped thread, thus resulting in deadlock.
sample->process_milestones = subtle::NoBarrier_Load(&process_milestones_);
}
// StackSamplingProfiler::Frame global functions ------------------------------
bool operator==(const StackSamplingProfiler::Module& a,
......
......@@ -213,6 +213,43 @@ class BASE_EXPORT StackSamplingProfiler {
// thread-safe callback implementation.
using CompletedCallback = Callback<void(CallStackProfile)>;
// SamplingProfileBuilder receives the sampling data from NativeSampler and
// builds a CallStackProfile.
class BASE_EXPORT SamplingProfileBuilder {
public:
SamplingProfileBuilder(const CompletedCallback& callback);
~SamplingProfileBuilder();
// Records metadata associated with sample_.
void RecordAnnotations();
// Finishes the construction of profile_ with |profile_duration| and
// |sampling_period|. Runs callback_ to pass profile_. Invoked when sampling
// a Profile completes.
void OnProfileCompleted(TimeDelta profile_duration,
TimeDelta sampling_period);
// Records a new set of frames to sample_. Invoked when sampling a Sample
// completes.
void OnSampleCompleted(std::vector<Frame> frames);
// Returns the address of modules in profile_.
std::vector<Module>* modules() { return &profile_.modules; }
private:
// The collected stack samples.
CallStackProfile profile_;
// The current sample being recorded.
Sample sample_;
// Callback made when sampling a profile completes.
const CompletedCallback callback_;
DISALLOW_COPY_AND_ASSIGN(SamplingProfileBuilder);
};
// Creates a profiler for the CURRENT thread that sends a completed profile
// to |callback|. An optional |test_delegate| can be supplied by tests.
// The caller must ensure that this object gets destroyed before the current
......@@ -266,9 +303,6 @@ class BASE_EXPORT StackSamplingProfiler {
// the target thread.
class SamplingThread;
// Adds annotations to a Sample.
static void RecordAnnotations(Sample* sample);
// This global variables holds the current system state and is recorded with
// every captured sample, done on a separate thread which is why updates to
// this must be atomic. A PostTask to move the the updates to that thread
......@@ -294,6 +328,11 @@ class BASE_EXPORT StackSamplingProfiler {
// Stored until it can be passed to the NativeStackSampler created in Start().
NativeStackSamplerTestDelegate* const test_delegate_;
// Receives the sampling data and builds a CallStackProfile. The ownership of
// this object will be transferred to the sampling thread when thread sampling
// starts.
std::unique_ptr<SamplingProfileBuilder> profile_builder_;
DISALLOW_COPY_AND_ASSIGN(StackSamplingProfiler);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment