blob: 2634c7549282e4e38ae70d0e0d57cc0fdc91af2a [file] [log] [blame]
Xi Cheng859dfcc2018-07-02 23:06:411// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
6#define COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
7
Mike Wittmancb1067c2019-01-24 19:04:008#include <limits>
Xi Cheng859dfcc2018-07-02 23:06:419#include <map>
Alexei Filippov0f15e7a2019-02-14 21:34:2810#include <unordered_map>
11#include <utility>
Xi Chenge91f6fd2018-08-14 16:34:5612#include <vector>
Xi Cheng859dfcc2018-07-02 23:06:4113
Xi Cheng2e07c5d2018-07-03 21:01:2914#include "base/callback.h"
Alexei Filippov0f15e7a2019-02-14 21:34:2815#include "base/macros.h"
Mike Wittman56a735e2019-11-04 23:54:1316#include "base/optional.h"
Charlie Andrews584d908422019-04-25 21:35:3717#include "base/profiler/metadata_recorder.h"
Mike Wittman9606835b2019-03-26 17:08:0618#include "base/profiler/profile_builder.h"
Xi Chengeb46484d2018-08-15 01:00:2819#include "base/sampling_heap_profiler/module_cache.h"
Xi Cheng9358aa092018-08-28 16:11:1220#include "base/time/time.h"
Xi Cheng4dec7e42018-08-10 16:54:1121#include "components/metrics/call_stack_profile_params.h"
Xi Cheng9358aa092018-08-28 16:11:1222#include "components/metrics/child_call_stack_profile_collector.h"
Julie Jeongeun Kime91fd9b2019-09-24 02:45:5323#include "mojo/public/cpp/bindings/pending_remote.h"
Xi Cheng4dec7e42018-08-10 16:54:1124#include "third_party/metrics_proto/sampled_profile.pb.h"
Xi Cheng2e07c5d2018-07-03 21:01:2925
Xi Chengcbeecd902018-07-05 01:34:5626namespace metrics {
27
Mike Wittmancb1067c2019-01-24 19:04:0028// Interface that allows the CallStackProfileBuilder to provide ids for distinct
29// work items. Samples with the same id are tagged as coming from the same work
30// item in the recorded samples.
31class WorkIdRecorder {
32 public:
33 WorkIdRecorder() = default;
34 virtual ~WorkIdRecorder() = default;
35
36 // This function is invoked on the profiler thread while the target thread is
37 // suspended so must not take any locks, including indirectly through use of
38 // heap allocation, LOG, CHECK, or DCHECK.
39 virtual unsigned int RecordWorkId() const = 0;
40
41 WorkIdRecorder(const WorkIdRecorder&) = delete;
42 WorkIdRecorder& operator=(const WorkIdRecorder&) = delete;
43};
44
Xi Cheng9358aa092018-08-28 16:11:1245// An instance of the class is meant to be passed to base::StackSamplingProfiler
46// to collect profiles. The profiles collected are uploaded via the metrics log.
Xi Chengb2e858e52018-09-11 20:58:0347//
48// This uses the new StackSample encoding rather than the legacy Sample
49// encoding.
Mike Wittman9606835b2019-03-26 17:08:0650class CallStackProfileBuilder : public base::ProfileBuilder {
Xi Cheng859dfcc2018-07-02 23:06:4151 public:
Xi Cheng9358aa092018-08-28 16:11:1252 // |completed_callback| is made when sampling a profile completes. Other
53 // threads, including the UI thread, may block on callback completion so this
54 // should run as quickly as possible.
55 //
56 // IMPORTANT NOTE: The callback is invoked on a thread the profiler
57 // constructs, rather than on the thread used to construct the profiler, and
58 // thus the callback must be callable on any thread.
Alexei Filippovdbbde602018-09-08 00:17:2659 explicit CallStackProfileBuilder(
Xi Cheng9358aa092018-08-28 16:11:1260 const CallStackProfileParams& profile_params,
Mike Wittmancb1067c2019-01-24 19:04:0061 const WorkIdRecorder* work_id_recorder = nullptr,
Xi Cheng9358aa092018-08-28 16:11:1262 base::OnceClosure completed_callback = base::OnceClosure());
Xi Cheng859dfcc2018-07-02 23:06:4163
64 ~CallStackProfileBuilder() override;
65
Alexei Filippova8d3aba2019-05-24 18:20:5766 // Both weight and count are used by the heap profiler only.
67 void OnSampleCompleted(std::vector<base::Frame> frames,
68 size_t weight,
69 size_t count);
Alexei Filippova0f72502019-05-22 22:10:4470
Mike Wittman9606835b2019-03-26 17:08:0671 // base::ProfileBuilder:
Mike Wittmanb5121e92019-02-19 22:39:4172 base::ModuleCache* GetModuleCache() override;
Mike Wittmaneca368e2019-11-05 00:32:0273 void RecordMetadata(
74 base::ProfileBuilder::MetadataProvider* metadata_provider) override;
Mike Wittmanc51cafa2019-04-04 15:48:0175 void OnSampleCompleted(std::vector<base::Frame> frames) override;
Xi Cheng859dfcc2018-07-02 23:06:4176 void OnProfileCompleted(base::TimeDelta profile_duration,
77 base::TimeDelta sampling_period) override;
78
Mike Wittman2943c9c72018-08-31 19:28:5779 // Sets the callback to use for reporting browser process profiles. This
80 // indirection is required to avoid a dependency on unnecessary metrics code
81 // in child processes.
82 static void SetBrowserProcessReceiverCallback(
83 const base::RepeatingCallback<void(base::TimeTicks, SampledProfile)>&
84 callback);
85
Xi Cheng9358aa092018-08-28 16:11:1286 // Sets the CallStackProfileCollector interface from |browser_interface|.
87 // This function must be called within child processes.
88 static void SetParentProfileCollectorForChildProcess(
Julie Jeongeun Kime91fd9b2019-09-24 02:45:5389 mojo::PendingRemote<metrics::mojom::CallStackProfileCollector>
90 browser_interface);
Xi Cheng9358aa092018-08-28 16:11:1291
92 protected:
93 // Test seam.
94 virtual void PassProfilesToMetricsProvider(SampledProfile sampled_profile);
95
Xi Cheng859dfcc2018-07-02 23:06:4196 private:
Xi Chengb2e858e52018-09-11 20:58:0397 // The functor for Stack comparison.
98 struct StackComparer {
99 bool operator()(const CallStackProfile::Stack* stack1,
100 const CallStackProfile::Stack* stack2) const;
101 };
Xi Cheng859dfcc2018-07-02 23:06:41102
Mike Wittman56a735e2019-11-04 23:54:13103 // Comparison function for the metadata map.
104 struct MetadataKey;
105 struct MetadataKeyCompare {
106 bool operator()(const MetadataKey& a, const MetadataKey& b) const;
107 };
108
109 // Definitions for a map-based representation of sample metadata.
110 struct MetadataKey {
111 MetadataKey(uint64_t name_hash, base::Optional<int64_t> key);
112
113 MetadataKey(const MetadataKey& other);
114 MetadataKey& operator=(const MetadataKey& other);
115
116 // The name_hash and optional user-specified key uniquely identifies a
117 // metadata value. See base::MetadataRecorder for details.
118 uint64_t name_hash;
119 base::Optional<int64_t> key;
120 };
121 using MetadataMap = std::map<MetadataKey, int64_t, MetadataKeyCompare>;
122
123 // Creates the metdata map from the array of items.
124 MetadataMap CreateMetadataMap(base::ProfileBuilder::MetadataItemArray items,
125 size_t item_count);
126
127 // Returns all metadata items with new values in the current sample.
128 MetadataMap GetNewOrModifiedMetadataItems(const MetadataMap& current_items,
129 const MetadataMap& previous_items);
130
131 // Returns all metadata items deleted since the previous sample.
132 MetadataMap GetDeletedMetadataItems(const MetadataMap& current_items,
133 const MetadataMap& previous_items);
134
Mike Wittmane3d6b4482019-11-05 00:38:05135 // Creates MetadataItems for the currently active metadata, adding new name
136 // hashes to |metadata_name_hashes| if necessary. The same
137 // |metadata_name_hashes| must be passed to each invocation, and must not be
138 // modified outside this function.
139 google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem>
140 CreateSampleMetadata(
141 google::protobuf::RepeatedField<uint64_t>* metadata_name_hashes);
Charlie Andrews0bfceb22019-04-29 17:23:24142
Mike Wittmane3d6b4482019-11-05 00:38:05143 // Appends the |name_hash| to |name_hashes| if it's not already
144 // present. Returns its index in |name_hashes|.
145 size_t MaybeAppendNameHash(
146 uint64_t name_hash,
147 google::protobuf::RepeatedField<uint64_t>* metadata_name_hashes);
Charlie Andrews0bfceb22019-04-29 17:23:24148
Mike Wittmanb5121e92019-02-19 22:39:41149 // The module cache to use for the duration the sampling associated with this
150 // ProfileBuilder.
151 base::ModuleCache module_cache_;
152
Mike Wittmancb1067c2019-01-24 19:04:00153 unsigned int last_work_id_ = std::numeric_limits<unsigned int>::max();
154 bool is_continued_work_ = false;
155 const WorkIdRecorder* const work_id_recorder_;
156
Xi Chengb2e858e52018-09-11 20:58:03157 // The SampledProfile protobuf message which contains the collected stack
158 // samples.
159 SampledProfile sampled_profile_;
Xi Cheng859dfcc2018-07-02 23:06:41160
Xi Chengb2e858e52018-09-11 20:58:03161 // The indexes of stacks, indexed by stack's address.
162 std::map<const CallStackProfile::Stack*, int, StackComparer> stack_index_;
Xi Chenge91f6fd2018-08-14 16:34:56163
Mike Wittman4ad741e2019-02-22 23:48:21164 // The indexes of modules in the modules_ vector below..
165 std::unordered_map<const base::ModuleCache::Module*, size_t> module_index_;
Xi Cheng859dfcc2018-07-02 23:06:41166
Xi Chenge91f6fd2018-08-14 16:34:56167 // The distinct modules in the current profile.
Mike Wittman4ad741e2019-02-22 23:48:21168 std::vector<const base::ModuleCache::Module*> modules_;
Xi Chenge91f6fd2018-08-14 16:34:56169
Xi Cheng859dfcc2018-07-02 23:06:41170 // Callback made when sampling a profile completes.
Xi Cheng9358aa092018-08-28 16:11:12171 base::OnceClosure completed_callback_;
Xi Cheng859dfcc2018-07-02 23:06:41172
Xi Cheng9358aa092018-08-28 16:11:12173 // The start time of a profile collection.
174 const base::TimeTicks profile_start_time_;
175
Charlie Andrews0bfceb22019-04-29 17:23:24176 // The data fetched from the MetadataRecorder for the next sample.
Charlie Andrews81c58dc2019-07-11 02:53:46177 base::ProfileBuilder::MetadataItemArray metadata_items_;
Charlie Andrews72bc22f62019-04-16 19:19:01178 size_t metadata_item_count_ = 0;
Mike Wittman56a735e2019-11-04 23:54:13179
Charlie Andrews0bfceb22019-04-29 17:23:24180 // The data fetched from the MetadataRecorder for the previous sample.
Mike Wittman56a735e2019-11-04 23:54:13181 MetadataMap previous_items_;
Charlie Andrews72bc22f62019-04-16 19:19:01182
Alexei Filippov0f15e7a2019-02-14 21:34:28183 // Maps metadata hash to index in |metadata_name_hash| array.
184 std::unordered_map<uint64_t, int> metadata_hashes_cache_;
185
Xi Cheng859dfcc2018-07-02 23:06:41186 DISALLOW_COPY_AND_ASSIGN(CallStackProfileBuilder);
187};
188
Xi Chengcbeecd902018-07-05 01:34:56189} // namespace metrics
190
Xi Cheng859dfcc2018-07-02 23:06:41191#endif // COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_