• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
18 
19 #include <sys/types.h>
20 
21 #include <functional>
22 #include <string>
23 #include <string_view>
24 #include <vector>
25 
26 #include "meminfo.h"
27 
28 namespace android {
29 namespace meminfo {
30 
31 using VmaCallback = std::function<bool(Vma&)>;
32 
33 class ProcMemInfo final {
34     // Per-process memory accounting
35   public:
36     // Reset the working set accounting of the process via /proc/<pid>/clear_refs
37     static bool ResetWorkingSet(pid_t pid);
38 
39     ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0);
40 
41     const std::vector<Vma>& Maps();
42     const MemUsage& Usage();
43     const MemUsage& Wss();
44 
45     // Same as Maps() except, only valid for reading working set using CONFIG_IDLE_PAGE_TRACKING
46     // support in kernel. If the kernel support doesn't exist, the function will return an empty
47     // vector.
48     const std::vector<Vma>& MapsWithPageIdle();
49 
50     // Same as Maps() except, do not read the usage stats for each map.
51     const std::vector<Vma>& MapsWithoutUsageStats();
52 
53     // If MapsWithoutUsageStats was called, this function will fill in
54     // usage stats for this single vma. If 'use_kb' is true, the vma's
55     // usage will be populated in kilobytes instead of bytes.
56     bool FillInVmaStats(Vma& vma, bool use_kb = false);
57 
58     // If ReadMaps (with get_usage_stats == false) or MapsWithoutUsageStats was
59     // called, this function will fill in usage stats for all vmas in 'maps_'.
60     bool GetUsageStats(bool get_wss, bool use_pageidle = false, bool update_mem_usage = true);
61 
62     // Collect all 'vma' or 'maps' from /proc/<pid>/smaps and store them in 'maps_'.
63     // If 'collect_usage' is 'true', this method will populate 'usage_' as vmas are being
64     // collected. If 'collect_swap_offsets' is 'true', pagemap will be read in order to
65     // populate 'swap_offsets_'.
66     //
67     // Returns a constant reference to the vma vector after the collection is
68     // done.
69     //
70     // Each 'struct Vma' is *fully* populated by this method (unlike SmapsOrRollup).
71     const std::vector<Vma>& Smaps(const std::string& path = "", bool collect_usage = false,
72                                   bool collect_swap_offsets = false);
73 
74     // If 'use_smaps' is 'true' this method reads /proc/<pid>/smaps and calls the callback()
75     // for each vma or map that it finds, else if 'use_smaps' is false /proc/<pid>/maps is
76     // used instead. Each vma or map found, is converted to 'struct Vma' object which is then
77     // passed to the callback.
78     // Returns 'false' if the file is malformed.
79     bool ForEachVma(const VmaCallback& callback, bool use_smaps = true);
80 
81     // Reads all VMAs from /proc/<pid>/maps and calls the callback() for each one of them.
82     // Returns false in case of failure during parsing.
83     bool ForEachVmaFromMaps(const VmaCallback& callback);
84 
85     // Similar to other VMA reading methods, except this one allows passing a reusable buffer
86     // to store the /proc/<pid>/maps content
87     bool ForEachVmaFromMaps(const VmaCallback& callback, std::string& mapsBuffer);
88 
89     // Takes the existing VMAs in 'maps_' and calls the callback() for each one
90     // of them. This is intended to avoid parsing /proc/<pid>/maps or
91     // /proc/<pid>/smaps twice.
92     // Returns false if 'maps_' is empty.
93     bool ForEachExistingVma(const VmaCallback& callback);
94 
95     // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
96     // Pss and Private memory usage in 'stats'.  In particular, the method only populates the fields
97     // of the MemUsage structure that are intended to be used by Android's periodic Pss collection.
98     //
99     // The method populates the following statistics in order to be fast an efficient.
100     //   Pss
101     //   Rss
102     //   Uss
103     //   private_clean
104     //   private_dirty
105     //   SwapPss
106     // All other fields of MemUsage are zeroed.
107     bool SmapsOrRollup(MemUsage* stats) const;
108 
109     // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
110     // Pss.
111     // Returns 'true' on success and the value of Pss in the out parameter.
112     bool SmapsOrRollupPss(uint64_t* pss) const;
113 
114     // Used to parse /proc/<pid>/status and record the process's RSS memory as
115     // reported by VmRSS. This is cheaper than using smaps or maps. VmRSS as
116     // reported by the kernel is not accurate; one of the maps or smaps methods
117     // should be used if an estimate is not sufficient.
118     //
119     // Returns 'true' on success and the value of VmRSS in the out parameter.
120     bool StatusVmRSS(uint64_t* rss) const;
121 
122     const std::vector<uint64_t>& SwapOffsets();
123 
124     // Reads /proc/<pid>/pagemap for this process for each page within
125     // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma'
126     // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks
127     // are made to see if 'vma' is *valid*.
128     // Returns false if anything goes wrong, 'true' otherwise.
129     bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap);
130 
131     ~ProcMemInfo() = default;
132 
133   private:
134     bool ReadMaps(bool get_wss, bool use_pageidle = false, bool get_usage_stats = true,
135                   bool update_mem_usage = true);
136     bool ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle,
137                       bool update_mem_usage, bool update_swap_usage);
138 
139     pid_t pid_;
140     bool get_wss_;
141     uint64_t pgflags_;
142     uint64_t pgflags_mask_;
143 
144     std::vector<Vma> maps_;
145 
146     MemUsage usage_;
147     std::vector<uint64_t> swap_offsets_;
148 };
149 
150 // Makes callback for each 'vma' or 'map' found in file provided.
151 // If 'read_smaps_fields' is 'true', the file is expected to be in the
152 // same format as /proc/<pid>/smaps, else the file is expected to be
153 // formatted as /proc/<pid>/maps.
154 // Returns 'false' if the file is malformed.
155 bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback,
156                         bool read_smaps_fields = true);
157 
158 // Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the
159 // calling process has access to the /proc/<pid>/smaps_rollup.
160 // Returns 'false' if the file doesn't exist.
161 bool IsSmapsRollupSupported();
162 
163 // Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly
164 // from a file. The file MUST be in the same format as /proc/<pid>/smaps
165 // or /proc/<pid>/smaps_rollup
166 bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats);
167 
168 // Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly
169 // from a file and returns total Pss in kB. The file MUST be in the same format
170 // as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup
171 bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss);
172 
173 // Same as ProcMemInfo::StatusVmRSS but reads the statistics directly from a file.
174 // The file MUST be in the same format as /proc/<pid>/status.
175 bool StatusVmRSSFromFile(const std::string& path, uint64_t* rss);
176 
177 // The output format that can be specified by user.
178 enum class Format { INVALID = 0, RAW, JSON, CSV };
179 
180 Format GetFormat(std::string_view arg);
181 
182 std::string EscapeCsvString(const std::string& raw);
183 
184 std::string EscapeJsonString(const std::string& raw);
185 
186 }  // namespace meminfo
187 }  // namespace android
188