1 /* 2 * Copyright (C) 2018 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_TRACED_PROBES_PS_PROCESS_STATS_DATA_SOURCE_H_ 18 #define SRC_TRACED_PROBES_PS_PROCESS_STATS_DATA_SOURCE_H_ 19 20 #include <functional> 21 #include <limits> 22 #include <memory> 23 #include <unordered_map> 24 #include <utility> 25 #include <vector> 26 27 #include "perfetto/base/flat_set.h" 28 #include "perfetto/ext/base/scoped_file.h" 29 #include "perfetto/ext/base/weak_ptr.h" 30 #include "perfetto/ext/tracing/core/basic_types.h" 31 #include "perfetto/ext/tracing/core/trace_writer.h" 32 #include "perfetto/tracing/core/forward_decls.h" 33 #include "src/traced/probes/probes_data_source.h" 34 35 namespace perfetto { 36 37 namespace base { 38 class TaskRunner; 39 } 40 41 namespace protos { 42 namespace pbzero { 43 class ProcessTree; 44 class ProcessStats; 45 class ProcessStats_Process; 46 } // namespace pbzero 47 } // namespace protos 48 49 class ProcessStatsDataSource : public ProbesDataSource { 50 public: 51 static const ProbesDataSource::Descriptor descriptor; 52 53 ProcessStatsDataSource(base::TaskRunner*, 54 TracingSessionID, 55 std::unique_ptr<TraceWriter> writer, 56 const DataSourceConfig&); 57 ~ProcessStatsDataSource() override; 58 59 base::WeakPtr<ProcessStatsDataSource> GetWeakPtr() const; 60 void WriteAllProcesses(); 61 void OnPids(const base::FlatSet<int32_t>& pids); 62 void OnRenamePids(const base::FlatSet<int32_t>& pids); 63 void OnFds(const base::FlatSet<std::pair<pid_t, uint64_t>>& fds); 64 65 // ProbesDataSource implementation. 66 void Start() override; 67 void Flush(FlushRequestID, std::function<void()> callback) override; 68 void ClearIncrementalState() override; 69 on_demand_dumps_enabled()70 bool on_demand_dumps_enabled() const { return enable_on_demand_dumps_; } 71 72 // Virtual for testing. 73 virtual const char* GetProcMountpoint(); 74 virtual base::ScopedDir OpenProcDir(); 75 virtual std::string ReadProcPidFile(int32_t pid, const std::string& file); 76 77 private: 78 struct CachedProcessStats { 79 uint32_t vm_size_kb = std::numeric_limits<uint32_t>::max(); 80 uint32_t vm_rss_kb = std::numeric_limits<uint32_t>::max(); 81 uint32_t rss_anon_kb = std::numeric_limits<uint32_t>::max(); 82 uint32_t rss_file_kb = std::numeric_limits<uint32_t>::max(); 83 uint32_t rss_shmem_kb = std::numeric_limits<uint32_t>::max(); 84 uint32_t vm_swap_kb = std::numeric_limits<uint32_t>::max(); 85 uint32_t vm_locked_kb = std::numeric_limits<uint32_t>::max(); 86 uint32_t vm_hvm_kb = std::numeric_limits<uint32_t>::max(); 87 int32_t oom_score_adj = std::numeric_limits<int32_t>::max(); 88 uint32_t smr_rss_kb = std::numeric_limits<uint32_t>::max(); 89 uint32_t smr_pss_kb = std::numeric_limits<uint32_t>::max(); 90 uint32_t smr_pss_anon_kb = std::numeric_limits<uint32_t>::max(); 91 uint32_t smr_pss_file_kb = std::numeric_limits<uint32_t>::max(); 92 uint32_t smr_pss_shmem_kb = std::numeric_limits<uint32_t>::max(); 93 uint32_t smr_swap_pss_kb = std::numeric_limits<uint32_t>::max(); 94 uint64_t runtime_user_mode_ns = std::numeric_limits<uint64_t>::max(); 95 uint64_t runtime_kernel_mode_ns = std::numeric_limits<uint64_t>::max(); 96 // file descriptors 97 base::FlatSet<uint64_t> seen_fds; 98 }; 99 100 // Common functions. 101 ProcessStatsDataSource(const ProcessStatsDataSource&) = delete; 102 ProcessStatsDataSource& operator=(const ProcessStatsDataSource&) = delete; 103 104 void StartNewPacketIfNeeded(); 105 void FinalizeCurPacket(); 106 protos::pbzero::ProcessTree* GetOrCreatePsTree(); 107 protos::pbzero::ProcessStats* GetOrCreateStats(); 108 protos::pbzero::ProcessStats_Process* GetOrCreateStatsProcess(int32_t pid); 109 110 // Functions for snapshotting process/thread long-term info and relationships. 111 bool WriteProcess(int32_t pid, 112 const std::string& proc_status, 113 const std::string& proc_stat); 114 void WriteThread(int32_t tid, int32_t tgid); 115 void WriteDetailedThread(int32_t tid, 116 int32_t tgid, 117 const std::string& proc_status); 118 void WriteProcessOrThread(int32_t pid); 119 120 // Functions for periodically sampling process stats/counters. 121 static void Tick(base::WeakPtr<ProcessStatsDataSource>); 122 void WriteAllProcessStats(); 123 bool WriteProcessRuntimes(int32_t pid, const std::string& proc_stat); 124 bool WriteMemCounters(int32_t pid, const std::string& proc_status); 125 void WriteFds(int32_t pid); 126 void WriteSingleFd(int32_t pid, uint64_t fd); 127 128 // Scans /proc/pid/status and writes the ProcessTree packet for input pids. 129 void WriteProcessTree(const base::FlatSet<int32_t>&); 130 131 // Read and "latch" the current procfs scan-start timestamp, which 132 // we reset only in FinalizeCurPacket. 133 uint64_t CacheProcFsScanStartTimestamp(); 134 135 // Common fields used for both process/tree relationships and stats/counters. 136 base::TaskRunner* const task_runner_; 137 std::unique_ptr<TraceWriter> writer_; 138 TraceWriter::TracePacketHandle cur_packet_; 139 140 // Cached before-scan timestamp; zero means cached time is absent. 141 // By the time we create the trace packet into which we dump procfs 142 // scan results, we've already read at least one bit of data from 143 // procfs, and by that point, it's too late to snap a timestamp from 144 // before we started looking at procfs at all, which is what trace 145 // analysis wants. To solve this problem, we record the scan-start 146 // timestamp here when we first open something in procfs and use 147 // that time when we create the packet. 148 // We reset this field after each FinalizeCurPacket(). 149 uint64_t cur_procfs_scan_start_timestamp_ = 0; 150 151 // Fields for keeping track of the state of process/tree relationships. 152 protos::pbzero::ProcessTree* cur_ps_tree_ = nullptr; 153 bool record_thread_names_ = false; 154 bool enable_on_demand_dumps_ = true; 155 bool dump_all_procs_on_start_ = false; 156 bool resolve_process_fds_ = false; 157 bool scan_smaps_rollup_ = false; 158 bool record_process_age_ = false; 159 bool record_process_runtime_ = false; 160 161 // This set contains PIDs as per the Linux kernel notion of a PID (which is 162 // really a TID). In practice this set will contain all TIDs for all processes 163 // seen, not just the main thread id (aka thread group ID). 164 struct SeenPid { 165 int32_t pid; 166 int32_t tgid; 167 pidSeenPid168 SeenPid(int32_t _pid, int32_t _tgid = 0) : pid(_pid), tgid(_tgid) {} 169 // TODO(rsavitski): add comparator support to FlatSet 170 bool operator==(const SeenPid& other) const { return pid == other.pid; } 171 bool operator<(const SeenPid& other) const { return pid < other.pid; } 172 }; 173 base::FlatSet<SeenPid> seen_pids_; 174 175 // Fields for keeping track of the periodic stats/counters. 176 uint32_t poll_period_ms_ = 0; 177 uint64_t cache_ticks_ = 0; 178 protos::pbzero::ProcessStats* cur_ps_stats_ = nullptr; 179 protos::pbzero::ProcessStats_Process* cur_ps_stats_process_ = nullptr; 180 std::vector<bool> skip_mem_for_pids_; 181 182 // Cached process stats per process. Cleared every |cache_ttl_ticks_| * 183 // |poll_period_ms_| ms. 184 uint32_t process_stats_cache_ttl_ticks_ = 0; 185 std::unordered_map<int32_t, CachedProcessStats> process_stats_cache_; 186 187 // If true, the next trace packet will have the |incremental_state_cleared| 188 // flag set. Set initially and when handling a ClearIncrementalState call. 189 bool did_clear_incremental_state_ = true; 190 191 base::WeakPtrFactory<ProcessStatsDataSource> weak_factory_; // Keep last. 192 }; 193 194 } // namespace perfetto 195 196 #endif // SRC_TRACED_PROBES_PS_PROCESS_STATS_DATA_SOURCE_H_ 197