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