• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_PROFILING_PERF_PERF_PRODUCER_H_
18 #define SRC_PROFILING_PERF_PERF_PRODUCER_H_
19 
20 #include <deque>
21 #include <map>
22 #include <queue>
23 
24 #include <unistd.h>
25 
26 #include <unwindstack/Error.h>
27 #include <unwindstack/Regs.h>
28 
29 #include "perfetto/base/task_runner.h"
30 #include "perfetto/ext/base/optional.h"
31 #include "perfetto/ext/base/scoped_file.h"
32 #include "perfetto/ext/base/unix_socket.h"
33 #include "perfetto/ext/base/weak_ptr.h"
34 #include "perfetto/ext/tracing/core/basic_types.h"
35 #include "perfetto/ext/tracing/core/producer.h"
36 #include "perfetto/ext/tracing/core/trace_writer.h"
37 #include "perfetto/ext/tracing/core/tracing_service.h"
38 #include "src/profiling/common/callstack_trie.h"
39 #include "src/profiling/common/interning_output.h"
40 #include "src/profiling/common/unwind_support.h"
41 #include "src/profiling/perf/common_types.h"
42 #include "src/profiling/perf/event_config.h"
43 #include "src/profiling/perf/event_reader.h"
44 #include "src/profiling/perf/proc_descriptors.h"
45 #include "src/profiling/perf/unwinding.h"
46 #include "src/tracing/core/metatrace_writer.h"
47 
48 namespace perfetto {
49 namespace profiling {
50 
51 // TODO(rsavitski): describe the high-level architecture and threading. Rough
52 // summary in the mean time: three stages: (1) kernel buffer reader that parses
53 // the samples -> (2) callstack unwinder -> (3) interning and serialization of
54 // samples. This class handles stages (1) and (3) on the main thread. Unwinding
55 // is done by |Unwinder| on a dedicated thread.
56 class PerfProducer : public Producer,
57                      public ProcDescriptorDelegate,
58                      public Unwinder::Delegate {
59  public:
60   PerfProducer(ProcDescriptorGetter* proc_fd_getter,
61                base::TaskRunner* task_runner);
62   ~PerfProducer() override = default;
63 
64   PerfProducer(const PerfProducer&) = delete;
65   PerfProducer& operator=(const PerfProducer&) = delete;
66   PerfProducer(PerfProducer&&) = delete;
67   PerfProducer& operator=(PerfProducer&&) = delete;
68 
69   void ConnectWithRetries(const char* socket_name);
70 
71   // Producer impl:
72   void OnConnect() override;
73   void OnDisconnect() override;
OnTracingSetup()74   void OnTracingSetup() override {}
75   void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
76   void StartDataSource(DataSourceInstanceID instance_id,
77                        const DataSourceConfig& config) override;
78   void StopDataSource(DataSourceInstanceID instance_id) override;
79   void Flush(FlushRequestID flush_id,
80              const DataSourceInstanceID* data_source_ids,
81              size_t num_data_sources) override;
82   void ClearIncrementalState(const DataSourceInstanceID* data_source_ids,
83                              size_t num_data_sources) override;
84 
85   // ProcDescriptorDelegate impl:
86   void OnProcDescriptors(pid_t pid,
87                          base::ScopedFile maps_fd,
88                          base::ScopedFile mem_fd) override;
89 
90   // Unwinder::Delegate impl (callbacks from unwinder):
91   void PostEmitSample(DataSourceInstanceID ds_id,
92                       CompletedSample sample) override;
93   void PostEmitUnwinderSkippedSample(DataSourceInstanceID ds_id,
94                                      ParsedSample sample) override;
95   void PostFinishDataSourceStop(DataSourceInstanceID ds_id) override;
96 
97  private:
98   // State of the producer's connection to tracing service (traced).
99   enum State {
100     kNotStarted = 0,
101     kNotConnected,
102     kConnecting,
103     kConnected,
104   };
105 
106   // Represents the data source scoped view of a process. Specifically:
107   // * whether the process is in scope of the tracing session (if the latter
108   //   specifies a target filter).
109   // * the state of the (possibly asynchronous) lookup of /proc/<pid>/{maps,mem}
110   //   file descriptors, which are necessary for callstack unwinding of samples.
111   enum class ProcessTrackingStatus {
112     kInitial,
113     kResolving,  // waiting on proc-fd lookup
114     kResolved,   // proc-fds obtained, and process considered relevant
115     kExpired,    // proc-fd lookup timed out
116     kRejected    // process not considered relevant for the data source
117   };
118 
119   struct DataSourceState {
120     enum class Status { kActive, kShuttingDown };
121 
DataSourceStateDataSourceState122     DataSourceState(EventConfig _event_config,
123                     std::unique_ptr<TraceWriter> _trace_writer,
124                     std::vector<EventReader> _per_cpu_readers)
125         : event_config(std::move(_event_config)),
126           trace_writer(std::move(_trace_writer)),
127           per_cpu_readers(std::move(_per_cpu_readers)) {}
128 
129     Status status = Status::kActive;
130     const EventConfig event_config;
131     std::unique_ptr<TraceWriter> trace_writer;
132     // Indexed by cpu, vector never resized.
133     std::vector<EventReader> per_cpu_readers;
134     // Tracks the incremental state for interned entries.
135     InterningOutputTracker interning_output;
136     // Producer thread's view of sampled processes. This is the primary tracking
137     // structure, but a subset of updates are replicated to a similar structure
138     // in the |Unwinder|, which needs to track whether the necessary unwinding
139     // inputs for a given process' samples are ready.
140     std::map<pid_t, ProcessTrackingStatus> process_states;
141   };
142 
143   // For |EmitSkippedSample|.
144   enum class SampleSkipReason {
145     kReadStage = 0,  // discarded at read stage
146     kUnwindEnqueue,  // discarded due to unwinder queue being full
147     kUnwindStage,    // discarded at unwind stage
148   };
149 
150   void ConnectService();
151   void Restart();
152   void ResetConnectionBackoff();
153   void IncreaseConnectionBackoff();
154 
155   // Periodic read task which reads a batch of samples from all kernel ring
156   // buffers associated with the given data source.
157   void TickDataSourceRead(DataSourceInstanceID ds_id);
158   // Returns *false* if the reader has caught up with the writer position, true
159   // otherwise. Return value is only useful if the underlying perf_event has
160   // been paused (to identify when the buffer is empty). |max_samples| is a cap
161   // on the amount of samples that will be parsed, which might be more than the
162   // number of underlying records (as there might be non-sample records).
163   bool ReadAndParsePerCpuBuffer(EventReader* reader,
164                                 uint32_t max_samples,
165                                 DataSourceInstanceID ds_id,
166                                 DataSourceState* ds);
167 
168   void InitiateDescriptorLookup(DataSourceInstanceID ds_id,
169                                 pid_t pid,
170                                 uint32_t timeout_ms);
171   // Do not call directly, use |InitiateDescriptorLookup|.
172   void StartDescriptorLookup(DataSourceInstanceID ds_id,
173                              pid_t pid,
174                              uint32_t timeout_ms);
175   void EvaluateDescriptorLookupTimeout(DataSourceInstanceID ds_id, pid_t pid);
176 
177   void EmitSample(DataSourceInstanceID ds_id, CompletedSample sample);
178   void EmitRingBufferLoss(DataSourceInstanceID ds_id,
179                           size_t cpu,
180                           uint64_t records_lost);
181 
182   void PostEmitSkippedSample(DataSourceInstanceID ds_id,
183                              ParsedSample sample,
184                              SampleSkipReason reason);
185   // Emit a packet indicating that a sample was relevant, but skipped as it was
186   // considered to be not unwindable (e.g. the process no longer exists).
187   void EmitSkippedSample(DataSourceInstanceID ds_id,
188                          ParsedSample sample,
189                          SampleSkipReason reason);
190 
191   // Starts the shutdown of the given data source instance, starting with
192   // pausing the reader frontend. Once the reader reaches the point where all
193   // kernel buffers have been fully consumed, it will notify the |Unwinder| to
194   // proceed with the shutdown sequence. The unwinder in turn will call back to
195   // this producer once there are no more outstanding samples for the data
196   // source at the unwinding stage.
197   void InitiateReaderStop(DataSourceState* ds);
198   // Destroys the state belonging to this instance, and acks the stop to the
199   // tracing service.
200   void FinishDataSourceStop(DataSourceInstanceID ds_id);
201 
202   void StartMetatraceSource(DataSourceInstanceID ds_id, BufferID target_buffer);
203 
204   // Task runner owned by the main thread.
205   base::TaskRunner* const task_runner_;
206   State state_ = kNotStarted;
207   const char* producer_socket_name_ = nullptr;
208   uint32_t connection_backoff_ms_ = 0;
209 
210   // Valid and stable for the lifetime of this class.
211   ProcDescriptorGetter* const proc_fd_getter_;
212 
213   // Owns shared memory, must outlive trace writing.
214   std::unique_ptr<TracingService::ProducerEndpoint> endpoint_;
215 
216   // If multiple metatrace sources are enabled concurrently,
217   // only the first one becomes active.
218   std::map<DataSourceInstanceID, MetatraceWriter> metatrace_writers_;
219 
220   // Interns callstacks across all data sources.
221   // TODO(rsavitski): for long profiling sessions, consider purging trie when it
222   // grows too large (at the moment purged only when no sources are active).
223   // TODO(rsavitski): interning sequences are monotonic for the lifetime of the
224   // daemon. Consider resetting them at safe points - possible when no sources
225   // are active, and tricky otherwise. In the latter case, it'll require
226   // emitting incremental sequence invalidation packets on all relevant
227   // sequences.
228   GlobalCallstackTrie callstack_trie_;
229 
230   // State associated with perf-sampling data sources.
231   std::map<DataSourceInstanceID, DataSourceState> data_sources_;
232 
233   // Unwinding stage, running on a dedicated thread.
234   UnwinderHandle unwinding_worker_;
235 
236   base::WeakPtrFactory<PerfProducer> weak_factory_;  // keep last
237 };
238 
239 }  // namespace profiling
240 }  // namespace perfetto
241 
242 #endif  // SRC_PROFILING_PERF_PERF_PRODUCER_H_
243