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 <limits> 21 #include <memory> 22 #include <set> 23 #include <unordered_map> 24 #include <vector> 25 26 #include "perfetto/base/scoped_file.h" 27 #include "perfetto/base/weak_ptr.h" 28 #include "perfetto/tracing/core/basic_types.h" 29 #include "perfetto/tracing/core/data_source_config.h" 30 #include "perfetto/tracing/core/trace_writer.h" 31 #include "src/traced/probes/probes_data_source.h" 32 33 namespace perfetto { 34 35 namespace base { 36 class TaskRunner; 37 } 38 39 namespace protos { 40 namespace pbzero { 41 class ProcessTree; 42 class ProcessStats; 43 class ProcessStats_Process; 44 } // namespace pbzero 45 } // namespace protos 46 47 class ProcessStatsDataSource : public ProbesDataSource { 48 public: 49 static constexpr int kTypeId = 3; 50 51 ProcessStatsDataSource(base::TaskRunner*, 52 TracingSessionID, 53 std::unique_ptr<TraceWriter> writer, 54 const DataSourceConfig&); 55 ~ProcessStatsDataSource() override; 56 57 base::WeakPtr<ProcessStatsDataSource> GetWeakPtr() const; 58 void WriteAllProcesses(); 59 void OnPids(const std::vector<int32_t>& pids); 60 void OnRenamePids(const std::vector<int32_t>& pids); 61 62 // ProbesDataSource implementation. 63 void Start() override; 64 void Flush(FlushRequestID, std::function<void()> callback) override; 65 void ClearIncrementalState() override; 66 67 bool on_demand_dumps_enabled() const { return enable_on_demand_dumps_; } 68 69 // Virtual for testing. 70 virtual base::ScopedDir OpenProcDir(); 71 virtual std::string ReadProcPidFile(int32_t pid, const std::string& file); 72 73 private: 74 struct CachedProcessStats { 75 uint32_t vm_size_kb = std::numeric_limits<uint32_t>::max(); 76 uint32_t vm_rss_kb = std::numeric_limits<uint32_t>::max(); 77 uint32_t rss_anon_kb = std::numeric_limits<uint32_t>::max(); 78 uint32_t rss_file_kb = std::numeric_limits<uint32_t>::max(); 79 uint32_t rss_shmem_kb = std::numeric_limits<uint32_t>::max(); 80 uint32_t vm_swap_kb = std::numeric_limits<uint32_t>::max(); 81 uint32_t vm_locked_kb = std::numeric_limits<uint32_t>::max(); 82 uint32_t vm_hvm_kb = std::numeric_limits<uint32_t>::max(); 83 int oom_score_adj = std::numeric_limits<int>::max(); 84 }; 85 86 // Common functions. 87 ProcessStatsDataSource(const ProcessStatsDataSource&) = delete; 88 ProcessStatsDataSource& operator=(const ProcessStatsDataSource&) = delete; 89 90 void StartNewPacketIfNeeded(); 91 void FinalizeCurPacket(); 92 protos::pbzero::ProcessTree* GetOrCreatePsTree(); 93 protos::pbzero::ProcessStats* GetOrCreateStats(); 94 protos::pbzero::ProcessStats_Process* GetOrCreateStatsProcess(int32_t pid); 95 96 // Functions for snapshotting process/thread long-term info and relationships. 97 void WriteProcess(int32_t pid, const std::string& proc_status); 98 void WriteThread(int32_t tid, int32_t tgid, const char* optional_name); 99 void WriteProcessOrThread(int32_t pid); 100 std::string ReadProcStatusEntry(const std::string& buf, const char* key); 101 102 // Functions for periodically sampling process stats/counters. 103 static void Tick(base::WeakPtr<ProcessStatsDataSource>); 104 void WriteAllProcessStats(); 105 bool WriteMemCounters(int32_t pid, const std::string& proc_status); 106 107 // Read and "latch" the current procfs scan-start timestamp, which 108 // we reset only in FinalizeCurPacket. 109 uint64_t CacheProcFsScanStartTimestamp(); 110 111 // Common fields used for both process/tree relationships and stats/counters. 112 base::TaskRunner* const task_runner_; 113 std::unique_ptr<TraceWriter> writer_; 114 TraceWriter::TracePacketHandle cur_packet_; 115 116 // Cached before-scan timestamp; zero means cached time is absent. 117 // By the time we create the trace packet into which we dump procfs 118 // scan results, we've already read at least one bit of data from 119 // procfs, and by that point, it's too late to snap a timestamp from 120 // before we started looking at procfs at all, which is what trace 121 // analysis wants. To solve this problem, we record the scan-start 122 // timestamp here when we first open something in procfs and use 123 // that time when we create the packet. 124 // We reset this field after each FinalizeCurPacket(). 125 uint64_t cur_procfs_scan_start_timestamp_ = 0; 126 127 // Fields for keeping track of the state of process/tree relationships. 128 protos::pbzero::ProcessTree* cur_ps_tree_ = nullptr; 129 bool record_thread_names_ = false; 130 bool enable_on_demand_dumps_ = true; 131 bool dump_all_procs_on_start_ = false; 132 133 // This set contains PIDs as per the Linux kernel notion of a PID (which is 134 // really a TID). In practice this set will contain all TIDs for all processes 135 // seen, not just the main thread id (aka thread group ID). 136 std::set<int32_t> seen_pids_; 137 138 // Fields for keeping track of the periodic stats/counters. 139 uint32_t poll_period_ms_ = 0; 140 uint64_t cache_ticks_ = 0; 141 protos::pbzero::ProcessStats* cur_ps_stats_ = nullptr; 142 protos::pbzero::ProcessStats_Process* cur_ps_stats_process_ = nullptr; 143 std::vector<bool> skip_stats_for_pids_; 144 145 // Cached process stats per process. Cleared every |cache_ttl_ticks_| * 146 // |poll_period_ms_| ms. 147 uint32_t process_stats_cache_ttl_ticks_ = 0; 148 std::unordered_map<int32_t, CachedProcessStats> process_stats_cache_; 149 150 // If true, the next trace packet will have the |incremental_state_cleared| 151 // flag set. Set when handling a ClearIncrementalState call. 152 // 153 // TODO(rsavitski): initialized to true since the first packet also doesn't 154 // have any prior state to refer to. It might make more sense to let the 155 // tracing service set this for every first packet (as it does for 156 // |previous_packet_dropped|). 157 bool did_clear_incremental_state_ = true; 158 159 base::WeakPtrFactory<ProcessStatsDataSource> weak_factory_; // Keep last. 160 }; 161 162 } // namespace perfetto 163 164 #endif // SRC_TRACED_PROBES_PS_PROCESS_STATS_DATA_SOURCE_H_ 165