1// Copyright 2019 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package procfs 15 16import ( 17 "bufio" 18 "bytes" 19 "fmt" 20 "io" 21 "strconv" 22 "strings" 23 24 "github.com/prometheus/procfs/internal/util" 25) 26 27// Meminfo represents memory statistics. 28type Meminfo struct { 29 // Total usable ram (i.e. physical ram minus a few reserved 30 // bits and the kernel binary code) 31 MemTotal uint64 32 // The sum of LowFree+HighFree 33 MemFree uint64 34 // An estimate of how much memory is available for starting 35 // new applications, without swapping. Calculated from 36 // MemFree, SReclaimable, the size of the file LRU lists, and 37 // the low watermarks in each zone. The estimate takes into 38 // account that the system needs some page cache to function 39 // well, and that not all reclaimable slab will be 40 // reclaimable, due to items being in use. The impact of those 41 // factors will vary from system to system. 42 MemAvailable uint64 43 // Relatively temporary storage for raw disk blocks shouldn't 44 // get tremendously large (20MB or so) 45 Buffers uint64 46 Cached uint64 47 // Memory that once was swapped out, is swapped back in but 48 // still also is in the swapfile (if memory is needed it 49 // doesn't need to be swapped out AGAIN because it is already 50 // in the swapfile. This saves I/O) 51 SwapCached uint64 52 // Memory that has been used more recently and usually not 53 // reclaimed unless absolutely necessary. 54 Active uint64 55 // Memory which has been less recently used. It is more 56 // eligible to be reclaimed for other purposes 57 Inactive uint64 58 ActiveAnon uint64 59 InactiveAnon uint64 60 ActiveFile uint64 61 InactiveFile uint64 62 Unevictable uint64 63 Mlocked uint64 64 // total amount of swap space available 65 SwapTotal uint64 66 // Memory which has been evicted from RAM, and is temporarily 67 // on the disk 68 SwapFree uint64 69 // Memory which is waiting to get written back to the disk 70 Dirty uint64 71 // Memory which is actively being written back to the disk 72 Writeback uint64 73 // Non-file backed pages mapped into userspace page tables 74 AnonPages uint64 75 // files which have been mapped, such as libraries 76 Mapped uint64 77 Shmem uint64 78 // in-kernel data structures cache 79 Slab uint64 80 // Part of Slab, that might be reclaimed, such as caches 81 SReclaimable uint64 82 // Part of Slab, that cannot be reclaimed on memory pressure 83 SUnreclaim uint64 84 KernelStack uint64 85 // amount of memory dedicated to the lowest level of page 86 // tables. 87 PageTables uint64 88 // NFS pages sent to the server, but not yet committed to 89 // stable storage 90 NFSUnstable uint64 91 // Memory used for block device "bounce buffers" 92 Bounce uint64 93 // Memory used by FUSE for temporary writeback buffers 94 WritebackTmp uint64 95 // Based on the overcommit ratio ('vm.overcommit_ratio'), 96 // this is the total amount of memory currently available to 97 // be allocated on the system. This limit is only adhered to 98 // if strict overcommit accounting is enabled (mode 2 in 99 // 'vm.overcommit_memory'). 100 // The CommitLimit is calculated with the following formula: 101 // CommitLimit = ([total RAM pages] - [total huge TLB pages]) * 102 // overcommit_ratio / 100 + [total swap pages] 103 // For example, on a system with 1G of physical RAM and 7G 104 // of swap with a `vm.overcommit_ratio` of 30 it would 105 // yield a CommitLimit of 7.3G. 106 // For more details, see the memory overcommit documentation 107 // in vm/overcommit-accounting. 108 CommitLimit uint64 109 // The amount of memory presently allocated on the system. 110 // The committed memory is a sum of all of the memory which 111 // has been allocated by processes, even if it has not been 112 // "used" by them as of yet. A process which malloc()'s 1G 113 // of memory, but only touches 300M of it will show up as 114 // using 1G. This 1G is memory which has been "committed" to 115 // by the VM and can be used at any time by the allocating 116 // application. With strict overcommit enabled on the system 117 // (mode 2 in 'vm.overcommit_memory'),allocations which would 118 // exceed the CommitLimit (detailed above) will not be permitted. 119 // This is useful if one needs to guarantee that processes will 120 // not fail due to lack of memory once that memory has been 121 // successfully allocated. 122 CommittedAS uint64 123 // total size of vmalloc memory area 124 VmallocTotal uint64 125 // amount of vmalloc area which is used 126 VmallocUsed uint64 127 // largest contiguous block of vmalloc area which is free 128 VmallocChunk uint64 129 HardwareCorrupted uint64 130 AnonHugePages uint64 131 ShmemHugePages uint64 132 ShmemPmdMapped uint64 133 CmaTotal uint64 134 CmaFree uint64 135 HugePagesTotal uint64 136 HugePagesFree uint64 137 HugePagesRsvd uint64 138 HugePagesSurp uint64 139 Hugepagesize uint64 140 DirectMap4k uint64 141 DirectMap2M uint64 142 DirectMap1G uint64 143} 144 145// Meminfo returns an information about current kernel/system memory statistics. 146// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt 147func (fs FS) Meminfo() (Meminfo, error) { 148 b, err := util.ReadFileNoStat(fs.proc.Path("meminfo")) 149 if err != nil { 150 return Meminfo{}, err 151 } 152 153 m, err := parseMemInfo(bytes.NewReader(b)) 154 if err != nil { 155 return Meminfo{}, fmt.Errorf("failed to parse meminfo: %v", err) 156 } 157 158 return *m, nil 159} 160 161func parseMemInfo(r io.Reader) (*Meminfo, error) { 162 var m Meminfo 163 s := bufio.NewScanner(r) 164 for s.Scan() { 165 // Each line has at least a name and value; we ignore the unit. 166 fields := strings.Fields(s.Text()) 167 if len(fields) < 2 { 168 return nil, fmt.Errorf("malformed meminfo line: %q", s.Text()) 169 } 170 171 v, err := strconv.ParseUint(fields[1], 0, 64) 172 if err != nil { 173 return nil, err 174 } 175 176 switch fields[0] { 177 case "MemTotal:": 178 m.MemTotal = v 179 case "MemFree:": 180 m.MemFree = v 181 case "MemAvailable:": 182 m.MemAvailable = v 183 case "Buffers:": 184 m.Buffers = v 185 case "Cached:": 186 m.Cached = v 187 case "SwapCached:": 188 m.SwapCached = v 189 case "Active:": 190 m.Active = v 191 case "Inactive:": 192 m.Inactive = v 193 case "Active(anon):": 194 m.ActiveAnon = v 195 case "Inactive(anon):": 196 m.InactiveAnon = v 197 case "Active(file):": 198 m.ActiveFile = v 199 case "Inactive(file):": 200 m.InactiveFile = v 201 case "Unevictable:": 202 m.Unevictable = v 203 case "Mlocked:": 204 m.Mlocked = v 205 case "SwapTotal:": 206 m.SwapTotal = v 207 case "SwapFree:": 208 m.SwapFree = v 209 case "Dirty:": 210 m.Dirty = v 211 case "Writeback:": 212 m.Writeback = v 213 case "AnonPages:": 214 m.AnonPages = v 215 case "Mapped:": 216 m.Mapped = v 217 case "Shmem:": 218 m.Shmem = v 219 case "Slab:": 220 m.Slab = v 221 case "SReclaimable:": 222 m.SReclaimable = v 223 case "SUnreclaim:": 224 m.SUnreclaim = v 225 case "KernelStack:": 226 m.KernelStack = v 227 case "PageTables:": 228 m.PageTables = v 229 case "NFS_Unstable:": 230 m.NFSUnstable = v 231 case "Bounce:": 232 m.Bounce = v 233 case "WritebackTmp:": 234 m.WritebackTmp = v 235 case "CommitLimit:": 236 m.CommitLimit = v 237 case "Committed_AS:": 238 m.CommittedAS = v 239 case "VmallocTotal:": 240 m.VmallocTotal = v 241 case "VmallocUsed:": 242 m.VmallocUsed = v 243 case "VmallocChunk:": 244 m.VmallocChunk = v 245 case "HardwareCorrupted:": 246 m.HardwareCorrupted = v 247 case "AnonHugePages:": 248 m.AnonHugePages = v 249 case "ShmemHugePages:": 250 m.ShmemHugePages = v 251 case "ShmemPmdMapped:": 252 m.ShmemPmdMapped = v 253 case "CmaTotal:": 254 m.CmaTotal = v 255 case "CmaFree:": 256 m.CmaFree = v 257 case "HugePages_Total:": 258 m.HugePagesTotal = v 259 case "HugePages_Free:": 260 m.HugePagesFree = v 261 case "HugePages_Rsvd:": 262 m.HugePagesRsvd = v 263 case "HugePages_Surp:": 264 m.HugePagesSurp = v 265 case "Hugepagesize:": 266 m.Hugepagesize = v 267 case "DirectMap4k:": 268 m.DirectMap4k = v 269 case "DirectMap2M:": 270 m.DirectMap2M = v 271 case "DirectMap1G:": 272 m.DirectMap1G = v 273 } 274 } 275 276 return &m, nil 277} 278