summaryrefslogtreecommitdiff
path: root/chromium/base/profiler/stack_sampling_profiler.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/profiler/stack_sampling_profiler.h')
-rw-r--r--chromium/base/profiler/stack_sampling_profiler.h205
1 files changed, 114 insertions, 91 deletions
diff --git a/chromium/base/profiler/stack_sampling_profiler.h b/chromium/base/profiler/stack_sampling_profiler.h
index 2f9ade55eea..e43349a8fe0 100644
--- a/chromium/base/profiler/stack_sampling_profiler.h
+++ b/chromium/base/profiler/stack_sampling_profiler.h
@@ -7,13 +7,12 @@
#include <stddef.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
-#include "base/atomicops.h"
#include "base/base_export.h"
-#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/strings/string16.h"
@@ -23,7 +22,9 @@
namespace base {
-class NativeStackSampler;
+// Identifies an unknown module.
+BASE_EXPORT extern const size_t kUnknownModuleIndex;
+
class NativeStackSamplerTestDelegate;
// StackSamplingProfiler periodically stops a thread to sample its stack, for
@@ -35,34 +36,24 @@ class NativeStackSamplerTestDelegate;
//
// // Create and customize params as desired.
// base::StackStackSamplingProfiler::SamplingParams params;
-// // Any thread's ID may be passed as the target.
-// base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
-// params);
//
-// // Or, to process the profiles within Chrome rather than via UMA, use a
-// // custom completed callback:
-// base::StackStackSamplingProfiler::CompletedCallback
-// thread_safe_callback = ...;
+// // To process the profiles, use a custom ProfileBuilder subclass:
+// class SubProfileBuilder :
+// public base::StackSamplingProfiler::ProfileBuilder{...}
// base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
-// params, thread_safe_callback);
+// params, std::make_unique<SubProfileBuilder>(...));
//
// profiler.Start();
// // ... work being done on the target thread here ...
// profiler.Stop(); // optional, stops collection before complete per params
//
-// The default SamplingParams causes stacks to be recorded in a single burst at
-// a 10Hz interval for a total of 30 seconds. All of these parameters may be
+// The default SamplingParams causes stacks to be recorded in a single profile
+// at a 10Hz interval for a total of 30 seconds. All of these parameters may be
// altered as desired.
//
-// When all call stack profiles are complete, or the profiler is stopped, the
-// completed callback is called from a thread created by the profiler with the
-// collected profiles.
-//
-// The results of the profiling are passed to the completed callback and consist
-// of a vector of CallStackProfiles. Each CallStackProfile corresponds to a
-// burst as specified in SamplingParams and contains a set of Samples and
-// Modules. One Sample corresponds to a single recorded stack, and the Modules
-// record those modules associated with the recorded stack frames.
+// When a call stack profile is complete, or the profiler is stopped,
+// ProfileBuilder's OnProfileCompleted function is called from a thread created
+// by the profiler.
class BASE_EXPORT StackSamplingProfiler {
public:
// Module represents the module (DLL or exe) corresponding to a stack frame.
@@ -89,11 +80,39 @@ class BASE_EXPORT StackSamplingProfiler {
FilePath filename;
};
+ // InternalModule represents the module (DLL or exe) and its validness state.
+ // Different from Module, it has an additional field "is_valid".
+ //
+ // This struct is only used for sampling data transfer from NativeStackSampler
+ // to ProfileBuilder.
+ struct BASE_EXPORT InternalModule {
+ InternalModule();
+ InternalModule(uintptr_t base_address,
+ const std::string& id,
+ const FilePath& filename);
+ ~InternalModule();
+
+ // Points to the base address of the module.
+ uintptr_t base_address;
+
+ // An opaque binary string that uniquely identifies a particular program
+ // version with high probability. This is parsed from headers of the loaded
+ // module.
+ // For binaries generated by GNU tools:
+ // Contents of the .note.gnu.build-id field.
+ // On Windows:
+ // GUID + AGE in the debug image headers of a module.
+ std::string id;
+
+ // The filename of the module.
+ FilePath filename;
+
+ // The validness of the module.
+ bool is_valid;
+ };
+
// Frame represents an individual sampled stack frame with module information.
struct BASE_EXPORT Frame {
- // Identifies an unknown module.
- static const size_t kUnknownModuleIndex = static_cast<size_t>(-1);
-
Frame(uintptr_t instruction_pointer, size_t module_index);
~Frame();
@@ -108,6 +127,23 @@ class BASE_EXPORT StackSamplingProfiler {
size_t module_index;
};
+ // InternalFrame represents an individual sampled stack frame with full module
+ // information. This is different from Frame which only contains module index.
+ //
+ // This struct is only used for sampling data transfer from NativeStackSampler
+ // to ProfileBuilder.
+ struct BASE_EXPORT InternalFrame {
+ InternalFrame(uintptr_t instruction_pointer,
+ InternalModule internal_module);
+ ~InternalFrame();
+
+ // The sampled instruction pointer within the function.
+ uintptr_t instruction_pointer;
+
+ // The module information.
+ InternalModule internal_module;
+ };
+
// Sample represents a set of stack frames with some extra information.
struct BASE_EXPORT Sample {
Sample();
@@ -157,24 +193,15 @@ class BASE_EXPORT StackSamplingProfiler {
DISALLOW_ASSIGN(CallStackProfile);
};
- using CallStackProfiles = std::vector<CallStackProfile>;
-
// Represents parameters that configure the sampling.
struct BASE_EXPORT SamplingParams {
// Time to delay before first samples are taken.
TimeDelta initial_delay = TimeDelta::FromMilliseconds(0);
- // Number of sampling bursts to perform.
- int bursts = 1;
-
- // Interval between sampling bursts. This is the desired duration from the
- // start of one burst to the start of the next burst.
- TimeDelta burst_interval = TimeDelta::FromSeconds(10);
-
- // Number of samples to record per burst.
- int samples_per_burst = 300;
+ // Number of samples to record per profile.
+ int samples_per_profile = 300;
- // Interval between samples during a sampling burst. This is the desired
+ // Interval between samples during a sampling profile. This is the desired
// duration from the start of one sample to the start of the next sample.
TimeDelta sampling_interval = TimeDelta::FromMilliseconds(100);
};
@@ -189,9 +216,6 @@ class BASE_EXPORT StackSamplingProfiler {
// so that tests don't inherit state from previous tests.
static void Reset();
- // Resets internal annotations (like process phase) to initial values.
- static void ResetAnnotations();
-
// Returns whether the sampling thread is currently running or not.
static bool IsSamplingThreadRunning();
@@ -211,41 +235,58 @@ class BASE_EXPORT StackSamplingProfiler {
bool simulate_intervening_start);
};
- // The callback type used to collect completed profiles. The passed |profiles|
- // are move-only. Other threads, including the UI thread, may block on
- // callback completion so this should run as quickly as possible.
- //
- // IMPORTANT NOTE: The callback is invoked on a thread the profiler
- // constructs, rather than on the thread used to construct the profiler and
- // set the callback, and thus the callback must be callable on any thread. For
- // threads with message loops that create StackSamplingProfilers, posting a
- // task to the message loop with the moved (i.e. std::move) profiles is the
- // thread-safe callback implementation.
- using CompletedCallback = Callback<void(CallStackProfiles)>;
-
- // Creates a profiler for the CURRENT thread that sends completed profiles
- // to |callback|. An optional |test_delegate| can be supplied by tests.
- // The caller must ensure that this object gets destroyed before the current
- // thread exits.
+ // The ProfileBuilder interface allows the user to record profile information
+ // on the fly in whatever format is desired. Functions are invoked by the
+ // profiler on its own thread so must not block or perform expensive
+ // operations.
+ class BASE_EXPORT ProfileBuilder {
+ public:
+ ProfileBuilder() = default;
+ virtual ~ProfileBuilder() = default;
+
+ // Metadata associated with the sample to be saved off.
+ // The code implementing 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.
+ virtual void RecordAnnotations() = 0;
+
+ // Records a new set of internal frames. Invoked when sampling a sample
+ // completes.
+ virtual void OnSampleCompleted(
+ std::vector<InternalFrame> internal_frames) = 0;
+
+ // Finishes the profile construction with |profile_duration| and
+ // |sampling_period|. Invoked when sampling a profile completes.
+ virtual void OnProfileCompleted(TimeDelta profile_duration,
+ TimeDelta sampling_period) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProfileBuilder);
+ };
+
+ // Creates a profiler for the CURRENT thread. An optional |test_delegate| can
+ // be supplied by tests. The caller must ensure that this object gets
+ // destroyed before the current thread exits.
StackSamplingProfiler(
const SamplingParams& params,
- const CompletedCallback& callback,
+ std::unique_ptr<ProfileBuilder> profile_builder,
NativeStackSamplerTestDelegate* test_delegate = nullptr);
- // Creates a profiler for ANOTHER thread that sends completed profiles to
- // |callback|. An optional |test_delegate| can be supplied by tests.
+ // Creates a profiler for ANOTHER thread. An optional |test_delegate| can be
+ // supplied by tests.
//
// IMPORTANT: The caller must ensure that the thread being sampled does not
// exit before this object gets destructed or Bad Things(tm) may occur.
StackSamplingProfiler(
PlatformThreadId thread_id,
const SamplingParams& params,
- const CompletedCallback& callback,
+ std::unique_ptr<ProfileBuilder> profile_builder,
NativeStackSamplerTestDelegate* test_delegate = nullptr);
// Stops any profiling currently taking place before destroying the profiler.
- // This will block until the callback has been run if profiling has started
- // but not already finished.
+ // This will block until profile_builder_'s OnProfileCompleted function has
+ // executed if profiling has started but not already finished.
~StackSamplingProfiler();
// Initializes the profiler and starts sampling. Might block on a
@@ -254,21 +295,13 @@ class BASE_EXPORT StackSamplingProfiler {
void Start();
// Stops the profiler and any ongoing sampling. This method will return
- // immediately with the callback being run asynchronously. At most one
- // more stack sample will be taken after this method returns. Calling this
- // function is optional; if not invoked profiling terminates when all the
- // profiling bursts specified in the SamplingParams are completed or the
- // profiler object is destroyed, whichever occurs first.
+ // immediately with the profile_builder_'s OnProfileCompleted function being
+ // run asynchronously. At most one more stack sample will be taken after this
+ // method returns. Calling this function is optional; if not invoked profiling
+ // terminates when all the profiling samples specified in the SamplingParams
+ // are completed or the profiler object is destroyed, whichever occurs first.
void Stop();
- // Set the current system state that is recorded with each captured stack
- // frame. This is thread-safe so can be called from anywhere. The parameter
- // value should be from an enumeration of the appropriate type with values
- // ranging from 0 to 31, inclusive. This sets bits within Sample field of
- // |process_milestones|. The actual meanings of these bits are defined
- // (globally) by the caller(s).
- static void SetProcessMilestone(int milestone);
-
private:
friend class TestAPI;
@@ -276,31 +309,21 @@ 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
- // would skew the timing and a lock could result in deadlock if the thread
- // making a change was also being profiled and got stopped.
- static subtle::Atomic32 process_milestones_;
-
// The thread whose stack will be sampled.
PlatformThreadId thread_id_;
const SamplingParams params_;
- const CompletedCallback completed_callback_;
+ // 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<ProfileBuilder> profile_builder_;
// This starts "signaled", is reset when sampling begins, and is signaled
- // when that sampling is complete and the callback done.
+ // when that sampling is complete and the profile_builder_'s
+ // OnProfileCompleted function has executed.
WaitableEvent profiling_inactive_;
- // Object that does the native sampling. This is created during construction
- // and later passed to the sampling thread when profiling is started.
- std::unique_ptr<NativeStackSampler> native_sampler_;
-
// An ID uniquely identifying this profiler to the sampling thread. This
// will be an internal "null" value when no collection has been started.
int profiler_id_;