1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
#define COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
#include <limits>
#include <map>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/profiler/metadata_recorder.h"
#include "base/profiler/module_cache.h"
#include "base/profiler/profile_builder.h"
#include "base/time/time.h"
#include "components/metrics/call_stack_profile_metadata.h"
#include "components/metrics/call_stack_profile_params.h"
#include "components/metrics/child_call_stack_profile_collector.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/metrics_proto/sampled_profile.pb.h"
namespace metrics {
// Interface that allows the CallStackProfileBuilder to provide ids for distinct
// work items. Samples with the same id are tagged as coming from the same work
// item in the recorded samples.
class WorkIdRecorder {
public:
WorkIdRecorder() = default;
virtual ~WorkIdRecorder() = default;
// This function is invoked on the profiler thread while the target thread is
// suspended so must not take any locks, including indirectly through use of
// heap allocation, LOG, CHECK, or DCHECK.
virtual unsigned int RecordWorkId() const = 0;
WorkIdRecorder(const WorkIdRecorder&) = delete;
WorkIdRecorder& operator=(const WorkIdRecorder&) = delete;
};
// An instance of the class is meant to be passed to base::StackSamplingProfiler
// to collect profiles. The profiles collected are uploaded via the metrics log.
//
// This uses the new StackSample encoding rather than the legacy Sample
// encoding.
class CallStackProfileBuilder : public base::ProfileBuilder {
public:
// |completed_callback| is made when sampling a profile completes. 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
// thus the callback must be callable on any thread.
explicit CallStackProfileBuilder(
const CallStackProfileParams& profile_params,
const WorkIdRecorder* work_id_recorder = nullptr,
base::OnceClosure completed_callback = base::OnceClosure());
CallStackProfileBuilder(const CallStackProfileBuilder&) = delete;
CallStackProfileBuilder& operator=(const CallStackProfileBuilder&) = delete;
~CallStackProfileBuilder() override;
// Both weight and count are used by the heap profiler only.
void OnSampleCompleted(std::vector<base::Frame> frames,
base::TimeTicks sample_timestamp,
size_t weight,
size_t count);
// base::ProfileBuilder:
base::ModuleCache* GetModuleCache() override;
void RecordMetadata(const base::MetadataRecorder::MetadataProvider&
metadata_provider) override;
void ApplyMetadataRetrospectively(
base::TimeTicks period_start,
base::TimeTicks period_end,
const base::MetadataRecorder::Item& item) override;
void AddProfileMetadata(const base::MetadataRecorder::Item& item) override;
void OnSampleCompleted(std::vector<base::Frame> frames,
base::TimeTicks sample_timestamp) override;
void OnProfileCompleted(base::TimeDelta profile_duration,
base::TimeDelta sampling_period) override;
// Sets the callback to use for reporting browser process profiles. This
// indirection is required to avoid a dependency on unnecessary metrics code
// in child processes.
static void SetBrowserProcessReceiverCallback(
const base::RepeatingCallback<void(base::TimeTicks, SampledProfile)>&
callback);
// Sets the CallStackProfileCollector interface from |browser_interface|.
// This function must be called within child processes, and must only be
// called once.
static void SetParentProfileCollectorForChildProcess(
mojo::PendingRemote<metrics::mojom::CallStackProfileCollector>
browser_interface);
// Resets the ChildCallStackProfileCollector to its default state. This will
// discard all collected profiles, remove any CallStackProfileCollector
// interface set through SetParentProfileCollectorForChildProcess, and allow
// SetParentProfileCollectorForChildProcess to be called multiple times during
// tests.
static void ResetChildCallStackProfileCollectorForTesting();
protected:
// Test seam.
virtual void PassProfilesToMetricsProvider(base::TimeTicks profile_start_time,
SampledProfile sampled_profile);
private:
// The functor for Stack comparison.
struct StackComparer {
bool operator()(const CallStackProfile::Stack* stack1,
const CallStackProfile::Stack* stack2) const;
};
// The module cache to use for the duration the sampling associated with this
// ProfileBuilder.
base::ModuleCache module_cache_;
unsigned int last_work_id_ = std::numeric_limits<unsigned int>::max();
bool is_continued_work_ = false;
const raw_ptr<const WorkIdRecorder> work_id_recorder_;
// The SampledProfile protobuf message which contains the collected stack
// samples.
SampledProfile sampled_profile_;
// The indexes of stacks, indexed by stack's address.
std::map<const CallStackProfile::Stack*, int, StackComparer> stack_index_;
// The indexes of modules in the modules_ vector below..
std::unordered_map<const base::ModuleCache::Module*, size_t> module_index_;
// The distinct modules in the current profile.
std::vector<const base::ModuleCache::Module*> modules_;
// Timestamps recording when each sample was taken.
std::vector<base::TimeTicks> sample_timestamps_;
// Callback made when sampling a profile completes.
base::OnceClosure completed_callback_;
// The start time of a profile collection.
base::TimeTicks profile_start_time_;
// Maintains the current metadata to apply to samples.
CallStackProfileMetadata metadata_;
};
} // namespace metrics
#endif // COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
|