blob: ddbc497bda69d43ebe011f197033db601158816f [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"
Charlie Andrews584d908422019-04-25 21:35:3716#include "base/profiler/metadata_recorder.h"
Mike Wittman9606835b2019-03-26 17:08:0617#include "base/profiler/profile_builder.h"
Xi Chengeb46484d2018-08-15 01:00:2818#include "base/sampling_heap_profiler/module_cache.h"
Xi Cheng9358aa092018-08-28 16:11:1219#include "base/time/time.h"
Xi Cheng4dec7e42018-08-10 16:54:1120#include "components/metrics/call_stack_profile_params.h"
Xi Cheng9358aa092018-08-28 16:11:1221#include "components/metrics/child_call_stack_profile_collector.h"
Xi Cheng4dec7e42018-08-10 16:54:1122#include "third_party/metrics_proto/sampled_profile.pb.h"
Xi Cheng2e07c5d2018-07-03 21:01:2923
Xi Chengcbeecd902018-07-05 01:34:5624namespace metrics {
25
Mike Wittmancb1067c2019-01-24 19:04:0026// Interface that allows the CallStackProfileBuilder to provide ids for distinct
27// work items. Samples with the same id are tagged as coming from the same work
28// item in the recorded samples.
29class WorkIdRecorder {
30 public:
31 WorkIdRecorder() = default;
32 virtual ~WorkIdRecorder() = default;
33
34 // This function is invoked on the profiler thread while the target thread is
35 // suspended so must not take any locks, including indirectly through use of
36 // heap allocation, LOG, CHECK, or DCHECK.
37 virtual unsigned int RecordWorkId() const = 0;
38
39 WorkIdRecorder(const WorkIdRecorder&) = delete;
40 WorkIdRecorder& operator=(const WorkIdRecorder&) = delete;
41};
42
Xi Cheng9358aa092018-08-28 16:11:1243// An instance of the class is meant to be passed to base::StackSamplingProfiler
44// to collect profiles. The profiles collected are uploaded via the metrics log.
Xi Chengb2e858e52018-09-11 20:58:0345//
46// This uses the new StackSample encoding rather than the legacy Sample
47// encoding.
Mike Wittman9606835b2019-03-26 17:08:0648class CallStackProfileBuilder : public base::ProfileBuilder {
Xi Cheng859dfcc2018-07-02 23:06:4149 public:
Xi Cheng9358aa092018-08-28 16:11:1250 // |completed_callback| is made when sampling a profile completes. Other
51 // threads, including the UI thread, may block on callback completion so this
52 // should run as quickly as possible.
53 //
54 // IMPORTANT NOTE: The callback is invoked on a thread the profiler
55 // constructs, rather than on the thread used to construct the profiler, and
56 // thus the callback must be callable on any thread.
Alexei Filippovdbbde602018-09-08 00:17:2657 explicit CallStackProfileBuilder(
Xi Cheng9358aa092018-08-28 16:11:1258 const CallStackProfileParams& profile_params,
Mike Wittmancb1067c2019-01-24 19:04:0059 const WorkIdRecorder* work_id_recorder = nullptr,
Charlie Andrews584d908422019-04-25 21:35:3760 const base::MetadataRecorder* metadata_recorder = nullptr,
Xi Cheng9358aa092018-08-28 16:11:1261 base::OnceClosure completed_callback = base::OnceClosure());
Xi Cheng859dfcc2018-07-02 23:06:4162
63 ~CallStackProfileBuilder() override;
64
Mike Wittman9606835b2019-03-26 17:08:0665 // base::ProfileBuilder:
Mike Wittmanb5121e92019-02-19 22:39:4166 base::ModuleCache* GetModuleCache() override;
Mike Wittmancb1067c2019-01-24 19:04:0067 void RecordMetadata() override;
Mike Wittmanc51cafa2019-04-04 15:48:0168 void OnSampleCompleted(std::vector<base::Frame> frames) override;
Xi Cheng859dfcc2018-07-02 23:06:4169 void OnProfileCompleted(base::TimeDelta profile_duration,
70 base::TimeDelta sampling_period) override;
71
Mike Wittman2943c9c72018-08-31 19:28:5772 // Sets the callback to use for reporting browser process profiles. This
73 // indirection is required to avoid a dependency on unnecessary metrics code
74 // in child processes.
75 static void SetBrowserProcessReceiverCallback(
76 const base::RepeatingCallback<void(base::TimeTicks, SampledProfile)>&
77 callback);
78
Xi Cheng9358aa092018-08-28 16:11:1279 // Sets the CallStackProfileCollector interface from |browser_interface|.
80 // This function must be called within child processes.
81 static void SetParentProfileCollectorForChildProcess(
82 metrics::mojom::CallStackProfileCollectorPtr browser_interface);
83
Xi Cheng9358aa092018-08-28 16:11:1284 protected:
85 // Test seam.
86 virtual void PassProfilesToMetricsProvider(SampledProfile sampled_profile);
87
Xi Cheng859dfcc2018-07-02 23:06:4188 private:
Xi Chengb2e858e52018-09-11 20:58:0389 // The functor for Stack comparison.
90 struct StackComparer {
91 bool operator()(const CallStackProfile::Stack* stack1,
92 const CallStackProfile::Stack* stack2) const;
93 };
Xi Cheng859dfcc2018-07-02 23:06:4194
Charlie Andrews0bfceb22019-04-29 17:23:2495 // Adds the already-collected metadata to the sample.
96 void AddSampleMetadata(CallStackProfile* profile,
97 CallStackProfile::StackSample* sample);
98
99 // Adds the specified name hash to the profile's name hash collection if it's
100 // not already in it. Returns the index of the name hash in the collection.
101 size_t MaybeAddNameHashToProfile(CallStackProfile* profile,
102 uint64_t name_hash);
103
Mike Wittmanb5121e92019-02-19 22:39:41104 // The module cache to use for the duration the sampling associated with this
105 // ProfileBuilder.
106 base::ModuleCache module_cache_;
107
Mike Wittmancb1067c2019-01-24 19:04:00108 unsigned int last_work_id_ = std::numeric_limits<unsigned int>::max();
109 bool is_continued_work_ = false;
110 const WorkIdRecorder* const work_id_recorder_;
Charlie Andrews584d908422019-04-25 21:35:37111 const base::MetadataRecorder* const metadata_recorder_;
Mike Wittmancb1067c2019-01-24 19:04:00112
Xi Chengb2e858e52018-09-11 20:58:03113 // The SampledProfile protobuf message which contains the collected stack
114 // samples.
115 SampledProfile sampled_profile_;
Xi Cheng859dfcc2018-07-02 23:06:41116
Xi Chengb2e858e52018-09-11 20:58:03117 // The indexes of stacks, indexed by stack's address.
118 std::map<const CallStackProfile::Stack*, int, StackComparer> stack_index_;
Xi Chenge91f6fd2018-08-14 16:34:56119
Mike Wittman4ad741e2019-02-22 23:48:21120 // The indexes of modules in the modules_ vector below..
121 std::unordered_map<const base::ModuleCache::Module*, size_t> module_index_;
Xi Cheng859dfcc2018-07-02 23:06:41122
Xi Chenge91f6fd2018-08-14 16:34:56123 // The distinct modules in the current profile.
Mike Wittman4ad741e2019-02-22 23:48:21124 std::vector<const base::ModuleCache::Module*> modules_;
Xi Chenge91f6fd2018-08-14 16:34:56125
Xi Cheng859dfcc2018-07-02 23:06:41126 // Callback made when sampling a profile completes.
Xi Cheng9358aa092018-08-28 16:11:12127 base::OnceClosure completed_callback_;
Xi Cheng859dfcc2018-07-02 23:06:41128
Xi Cheng9358aa092018-08-28 16:11:12129 // The start time of a profile collection.
130 const base::TimeTicks profile_start_time_;
131
Charlie Andrews0bfceb22019-04-29 17:23:24132 // The data fetched from the MetadataRecorder for the next sample.
Charlie Andrews584d908422019-04-25 21:35:37133 base::MetadataRecorder::ItemArray metadata_items_;
Charlie Andrews72bc22f62019-04-16 19:19:01134 size_t metadata_item_count_ = 0;
Charlie Andrews0bfceb22019-04-29 17:23:24135 // The data fetched from the MetadataRecorder for the previous sample.
136 std::map<uint64_t, int64_t> previous_items_;
Charlie Andrews72bc22f62019-04-16 19:19:01137
Alexei Filippov0f15e7a2019-02-14 21:34:28138 // Maps metadata hash to index in |metadata_name_hash| array.
139 std::unordered_map<uint64_t, int> metadata_hashes_cache_;
140
Xi Cheng859dfcc2018-07-02 23:06:41141 DISALLOW_COPY_AND_ASSIGN(CallStackProfileBuilder);
142};
143
Xi Chengcbeecd902018-07-05 01:34:56144} // namespace metrics
145
Xi Cheng859dfcc2018-07-02 23:06:41146#endif // COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_