• 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 <unistd.h>
21 #include <map>
22 #include <memory>
23 #include <optional>
24 
25 #include <unwindstack/Error.h>
26 #include <unwindstack/Regs.h>
27 
28 #include "perfetto/base/task_runner.h"
29 #include "perfetto/ext/base/scoped_file.h"
30 #include "perfetto/ext/base/unix_socket.h"
31 #include "perfetto/ext/base/weak_ptr.h"
32 #include "perfetto/ext/tracing/core/basic_types.h"
33 #include "perfetto/ext/tracing/core/producer.h"
34 #include "perfetto/ext/tracing/core/trace_writer.h"
35 #include "perfetto/ext/tracing/core/tracing_service.h"
36 #include "src/profiling/common/callstack_trie.h"
37 #include "src/profiling/common/interning_output.h"
38 #include "src/profiling/common/unwind_support.h"
39 #include "src/profiling/perf/common_types.h"
40 #include "src/profiling/perf/event_config.h"
41 #include "src/profiling/perf/event_reader.h"
42 #include "src/profiling/perf/proc_descriptors.h"
43 #include "src/profiling/perf/unwinding.h"
44 #include "src/tracing/core/metatrace_writer.h"
45 // TODO(rsavitski): move to e.g. src/tracefs/.
46 #include "src/traced/probes/ftrace/ftrace_procfs.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                          uid_t uid,
88                          base::ScopedFile maps_fd,
89                          base::ScopedFile mem_fd) override;
90 
91   // Unwinder::Delegate impl (callbacks from unwinder):
92   void PostEmitSample(DataSourceInstanceID ds_id,
93                       CompletedSample sample) override;
94   void PostEmitUnwinderSkippedSample(DataSourceInstanceID ds_id,
95                                      ParsedSample sample) override;
96   void PostFinishDataSourceStop(DataSourceInstanceID ds_id) override;
97 
98   // Calls `cb` when all data sources have been registered.
SetAllDataSourcesRegisteredCb(std::function<void ()> cb)99   void SetAllDataSourcesRegisteredCb(std::function<void()> cb) {
100     all_data_sources_registered_cb_ = cb;
101   }
102 
103   // public for testing:
104   static bool ShouldRejectDueToFilter(
105       pid_t pid,
106       const TargetFilter& filter,
107       bool skip_cmdline,
108       base::FlatSet<std::string>* additional_cmdlines,
109       std::function<bool(std::string*)> read_proc_pid_cmdline);
110 
111  private:
112   // State of the producer's connection to tracing service (traced).
113   enum State {
114     kNotStarted = 0,
115     kNotConnected,
116     kConnecting,
117     kConnected,
118   };
119 
120   // Represents the data source scoped view of a process:
121   // * whether the process is in scope of the tracing session (if the latter
122   //   specifies a callstack sampling target filter).
123   // * for userspace processes, the state of the (possibly asynchronous) lookup
124   //   of /proc/<pid>/{maps,mem} file descriptors, which are necessary for
125   //   callstack unwinding of samples.
126   // For kernel threads (or when sampling only kernelspace callstacks) the
127   // proc-fds are not necessary, so those processes transition directly to
128   // either kAccepted or kRejected.
129   // TODO(rsavitski): double-check and clarify pid reuse semantics. For
130   // userspace sampling, at most one incarnation of the pid is handled since we
131   // do not obtain new proc descriptors. But counter-only and kernel-only cases
132   // aren't as stateful and will keep emitting samples.
133   enum class ProcessTrackingStatus {
134     kInitial = 0,
135     kFdsResolving,  // waiting on proc-fd lookup
136     kAccepted,      // process relevant and ready for unwinding (for userspace -
137                     // procfds received)
138     kFdsTimedOut,   // proc-fd lookup timed out
139     kRejected       // process not considered relevant for the data source
140   };
141 
142   struct DataSourceState {
143     enum class Status { kActive, kShuttingDown };
144 
DataSourceStateDataSourceState145     DataSourceState(EventConfig _event_config,
146                     uint64_t _tracing_session_id,
147                     std::unique_ptr<TraceWriter> _trace_writer,
148                     std::vector<EventReader> _per_cpu_readers)
149         : event_config(std::move(_event_config)),
150           tracing_session_id(_tracing_session_id),
151           trace_writer(std::move(_trace_writer)),
152           per_cpu_readers(std::move(_per_cpu_readers)) {}
153 
154     Status status = Status::kActive;
155     const EventConfig event_config;
156     uint64_t tracing_session_id;
157     std::unique_ptr<TraceWriter> trace_writer;
158     // Indexed by cpu, vector never resized.
159     std::vector<EventReader> per_cpu_readers;
160     // Tracks the incremental state for interned entries.
161     InterningOutputTracker interning_output;
162     // Producer thread's view of sampled processes. This is the primary tracking
163     // structure, but a subset of updates are replicated to a similar structure
164     // in the |Unwinder|, which needs to track whether the necessary unwinding
165     // inputs for a given process' samples are ready.
166     std::map<pid_t, ProcessTrackingStatus> process_states;
167     // Additional state for EventConfig.TargetFilter: command lines we have
168     // decided to unwind, up to a total of additional_cmdline_count values.
169     base::FlatSet<std::string> additional_cmdlines;
170   };
171 
172   // For |EmitSkippedSample|.
173   enum class SampleSkipReason {
174     kReadStage = 0,  // discarded at read stage
175     kUnwindEnqueue,  // discarded due to unwinder queue being full
176     kUnwindStage,    // discarded at unwind stage
177   };
178 
179   void ConnectService();
180   void Restart();
181   void ResetConnectionBackoff();
182   void IncreaseConnectionBackoff();
183 
184   // Periodic read task which reads a batch of samples from all kernel ring
185   // buffers associated with the given data source.
186   void TickDataSourceRead(DataSourceInstanceID ds_id);
187   // Returns *false* if the reader has caught up with the writer position, true
188   // otherwise. Return value is only useful if the underlying perf_event has
189   // been paused (to identify when the buffer is empty). |max_samples| is a cap
190   // on the amount of samples that will be parsed, which might be more than the
191   // number of underlying records (as there might be non-sample records).
192   bool ReadAndParsePerCpuBuffer(EventReader* reader,
193                                 uint64_t max_samples,
194                                 DataSourceInstanceID ds_id,
195                                 DataSourceState* ds);
196 
197   void InitiateDescriptorLookup(DataSourceInstanceID ds_id,
198                                 pid_t pid,
199                                 uint32_t timeout_ms);
200   // Do not call directly, use |InitiateDescriptorLookup|.
201   void StartDescriptorLookup(DataSourceInstanceID ds_id,
202                              pid_t pid,
203                              uint32_t timeout_ms);
204   void EvaluateDescriptorLookupTimeout(DataSourceInstanceID ds_id, pid_t pid);
205 
206   void EmitSample(DataSourceInstanceID ds_id, CompletedSample sample);
207   void EmitRingBufferLoss(DataSourceInstanceID ds_id,
208                           size_t cpu,
209                           uint64_t records_lost);
210 
211   void PostEmitSkippedSample(DataSourceInstanceID ds_id,
212                              ParsedSample sample,
213                              SampleSkipReason reason);
214   // Emit a packet indicating that a sample was relevant, but skipped as it was
215   // considered to be not unwindable (e.g. the process no longer exists).
216   void EmitSkippedSample(DataSourceInstanceID ds_id,
217                          ParsedSample sample,
218                          SampleSkipReason reason);
219 
220   // Starts the shutdown of the given data source instance, starting with
221   // pausing the reader frontend. Once the reader reaches the point where all
222   // kernel buffers have been fully consumed, it will notify the |Unwinder| to
223   // proceed with the shutdown sequence. The unwinder in turn will call back to
224   // this producer once there are no more outstanding samples for the data
225   // source at the unwinding stage.
226   void InitiateReaderStop(DataSourceState* ds);
227   // Destroys the state belonging to this instance, and acks the stop to the
228   // tracing service.
229   void FinishDataSourceStop(DataSourceInstanceID ds_id);
230   // Immediately destroys the data source state, and instructs the unwinder to
231   // do the same. This is used for abrupt stops.
232   void PurgeDataSource(DataSourceInstanceID ds_id);
233 
234   // Immediately stops the data source if this daemon's overall memory footprint
235   // is above the given threshold. This periodic task is started only for data
236   // sources that specify a limit.
237   void CheckMemoryFootprintPeriodic(DataSourceInstanceID ds_id,
238                                     uint32_t max_daemon_memory_kb);
239 
240   // Chooses a random parameter for a callstack sampling option. Done at this
241   // level as the choice is shared by all data sources within a tracing session.
242   std::optional<ProcessSharding> GetOrChooseCallstackProcessShard(
243       uint64_t tracing_session_id,
244       uint32_t shard_count);
245 
246   void StartMetatraceSource(DataSourceInstanceID ds_id, BufferID target_buffer);
247 
248   // Task runner owned by the main thread.
249   base::TaskRunner* const task_runner_;
250   State state_ = kNotStarted;
251   const char* producer_socket_name_ = nullptr;
252   uint32_t connection_backoff_ms_ = 0;
253 
254   // Valid and stable for the lifetime of this class.
255   ProcDescriptorGetter* const proc_fd_getter_;
256 
257   // Owns shared memory, must outlive trace writing.
258   std::unique_ptr<TracingService::ProducerEndpoint> endpoint_;
259 
260   // If multiple metatrace sources are enabled concurrently,
261   // only the first one becomes active.
262   std::map<DataSourceInstanceID, MetatraceWriter> metatrace_writers_;
263 
264   // Interns callstacks across all data sources.
265   // TODO(rsavitski): for long profiling sessions, consider purging trie when it
266   // grows too large (at the moment purged only when no sources are active).
267   // TODO(rsavitski): interning sequences are monotonic for the lifetime of the
268   // daemon. Consider resetting them at safe points - possible when no sources
269   // are active, and tricky otherwise. In the latter case, it'll require
270   // emitting incremental sequence invalidation packets on all relevant
271   // sequences.
272   GlobalCallstackTrie callstack_trie_;
273 
274   // State associated with perf-sampling data sources.
275   std::map<DataSourceInstanceID, DataSourceState> data_sources_;
276 
277   // Unwinding stage, running on a dedicated thread.
278   UnwinderHandle unwinding_worker_;
279 
280   // Used for tracepoint name -> id lookups. Initialized lazily, and in general
281   // best effort - can be null if tracefs isn't accessible.
282   std::unique_ptr<FtraceProcfs> tracefs_;
283 
284   std::function<void()> all_data_sources_registered_cb_;
285 
286   base::WeakPtrFactory<PerfProducer> weak_factory_;  // keep last
287 };
288 
289 }  // namespace profiling
290 }  // namespace perfetto
291 
292 #endif  // SRC_PROFILING_PERF_PERF_PRODUCER_H_
293