meminfo.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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. package procfs
  14. import (
  15. "bufio"
  16. "bytes"
  17. "fmt"
  18. "io"
  19. "strconv"
  20. "strings"
  21. "github.com/prometheus/procfs/internal/util"
  22. )
  23. // Meminfo represents memory statistics.
  24. type Meminfo struct {
  25. // Total usable ram (i.e. physical ram minus a few reserved
  26. // bits and the kernel binary code)
  27. MemTotal *uint64
  28. // The sum of LowFree+HighFree
  29. MemFree *uint64
  30. // An estimate of how much memory is available for starting
  31. // new applications, without swapping. Calculated from
  32. // MemFree, SReclaimable, the size of the file LRU lists, and
  33. // the low watermarks in each zone. The estimate takes into
  34. // account that the system needs some page cache to function
  35. // well, and that not all reclaimable slab will be
  36. // reclaimable, due to items being in use. The impact of those
  37. // factors will vary from system to system.
  38. MemAvailable *uint64
  39. // Relatively temporary storage for raw disk blocks shouldn't
  40. // get tremendously large (20MB or so)
  41. Buffers *uint64
  42. Cached *uint64
  43. // Memory that once was swapped out, is swapped back in but
  44. // still also is in the swapfile (if memory is needed it
  45. // doesn't need to be swapped out AGAIN because it is already
  46. // in the swapfile. This saves I/O)
  47. SwapCached *uint64
  48. // Memory that has been used more recently and usually not
  49. // reclaimed unless absolutely necessary.
  50. Active *uint64
  51. // Memory which has been less recently used. It is more
  52. // eligible to be reclaimed for other purposes
  53. Inactive *uint64
  54. ActiveAnon *uint64
  55. InactiveAnon *uint64
  56. ActiveFile *uint64
  57. InactiveFile *uint64
  58. Unevictable *uint64
  59. Mlocked *uint64
  60. // total amount of swap space available
  61. SwapTotal *uint64
  62. // Memory which has been evicted from RAM, and is temporarily
  63. // on the disk
  64. SwapFree *uint64
  65. // Memory which is waiting to get written back to the disk
  66. Dirty *uint64
  67. // Memory which is actively being written back to the disk
  68. Writeback *uint64
  69. // Non-file backed pages mapped into userspace page tables
  70. AnonPages *uint64
  71. // files which have been mapped, such as libraries
  72. Mapped *uint64
  73. Shmem *uint64
  74. // in-kernel data structures cache
  75. Slab *uint64
  76. // Part of Slab, that might be reclaimed, such as caches
  77. SReclaimable *uint64
  78. // Part of Slab, that cannot be reclaimed on memory pressure
  79. SUnreclaim *uint64
  80. KernelStack *uint64
  81. // amount of memory dedicated to the lowest level of page
  82. // tables.
  83. PageTables *uint64
  84. // NFS pages sent to the server, but not yet committed to
  85. // stable storage
  86. NFSUnstable *uint64
  87. // Memory used for block device "bounce buffers"
  88. Bounce *uint64
  89. // Memory used by FUSE for temporary writeback buffers
  90. WritebackTmp *uint64
  91. // Based on the overcommit ratio ('vm.overcommit_ratio'),
  92. // this is the total amount of memory currently available to
  93. // be allocated on the system. This limit is only adhered to
  94. // if strict overcommit accounting is enabled (mode 2 in
  95. // 'vm.overcommit_memory').
  96. // The CommitLimit is calculated with the following formula:
  97. // CommitLimit = ([total RAM pages] - [total huge TLB pages]) *
  98. // overcommit_ratio / 100 + [total swap pages]
  99. // For example, on a system with 1G of physical RAM and 7G
  100. // of swap with a `vm.overcommit_ratio` of 30 it would
  101. // yield a CommitLimit of 7.3G.
  102. // For more details, see the memory overcommit documentation
  103. // in vm/overcommit-accounting.
  104. CommitLimit *uint64
  105. // The amount of memory presently allocated on the system.
  106. // The committed memory is a sum of all of the memory which
  107. // has been allocated by processes, even if it has not been
  108. // "used" by them as of yet. A process which malloc()'s 1G
  109. // of memory, but only touches 300M of it will show up as
  110. // using 1G. This 1G is memory which has been "committed" to
  111. // by the VM and can be used at any time by the allocating
  112. // application. With strict overcommit enabled on the system
  113. // (mode 2 in 'vm.overcommit_memory'),allocations which would
  114. // exceed the CommitLimit (detailed above) will not be permitted.
  115. // This is useful if one needs to guarantee that processes will
  116. // not fail due to lack of memory once that memory has been
  117. // successfully allocated.
  118. CommittedAS *uint64
  119. // total size of vmalloc memory area
  120. VmallocTotal *uint64
  121. // amount of vmalloc area which is used
  122. VmallocUsed *uint64
  123. // largest contiguous block of vmalloc area which is free
  124. VmallocChunk *uint64
  125. Percpu *uint64
  126. HardwareCorrupted *uint64
  127. AnonHugePages *uint64
  128. ShmemHugePages *uint64
  129. ShmemPmdMapped *uint64
  130. CmaTotal *uint64
  131. CmaFree *uint64
  132. HugePagesTotal *uint64
  133. HugePagesFree *uint64
  134. HugePagesRsvd *uint64
  135. HugePagesSurp *uint64
  136. Hugepagesize *uint64
  137. DirectMap4k *uint64
  138. DirectMap2M *uint64
  139. DirectMap1G *uint64
  140. // The struct fields below are the byte-normalized counterparts to the
  141. // existing struct fields. Values are normalized using the optional
  142. // unit field in the meminfo line.
  143. MemTotalBytes *uint64
  144. MemFreeBytes *uint64
  145. MemAvailableBytes *uint64
  146. BuffersBytes *uint64
  147. CachedBytes *uint64
  148. SwapCachedBytes *uint64
  149. ActiveBytes *uint64
  150. InactiveBytes *uint64
  151. ActiveAnonBytes *uint64
  152. InactiveAnonBytes *uint64
  153. ActiveFileBytes *uint64
  154. InactiveFileBytes *uint64
  155. UnevictableBytes *uint64
  156. MlockedBytes *uint64
  157. SwapTotalBytes *uint64
  158. SwapFreeBytes *uint64
  159. DirtyBytes *uint64
  160. WritebackBytes *uint64
  161. AnonPagesBytes *uint64
  162. MappedBytes *uint64
  163. ShmemBytes *uint64
  164. SlabBytes *uint64
  165. SReclaimableBytes *uint64
  166. SUnreclaimBytes *uint64
  167. KernelStackBytes *uint64
  168. PageTablesBytes *uint64
  169. NFSUnstableBytes *uint64
  170. BounceBytes *uint64
  171. WritebackTmpBytes *uint64
  172. CommitLimitBytes *uint64
  173. CommittedASBytes *uint64
  174. VmallocTotalBytes *uint64
  175. VmallocUsedBytes *uint64
  176. VmallocChunkBytes *uint64
  177. PercpuBytes *uint64
  178. HardwareCorruptedBytes *uint64
  179. AnonHugePagesBytes *uint64
  180. ShmemHugePagesBytes *uint64
  181. ShmemPmdMappedBytes *uint64
  182. CmaTotalBytes *uint64
  183. CmaFreeBytes *uint64
  184. HugepagesizeBytes *uint64
  185. DirectMap4kBytes *uint64
  186. DirectMap2MBytes *uint64
  187. DirectMap1GBytes *uint64
  188. }
  189. // Meminfo returns an information about current kernel/system memory statistics.
  190. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
  191. func (fs FS) Meminfo() (Meminfo, error) {
  192. b, err := util.ReadFileNoStat(fs.proc.Path("meminfo"))
  193. if err != nil {
  194. return Meminfo{}, err
  195. }
  196. m, err := parseMemInfo(bytes.NewReader(b))
  197. if err != nil {
  198. return Meminfo{}, fmt.Errorf("%w: %w", ErrFileParse, err)
  199. }
  200. return *m, nil
  201. }
  202. func parseMemInfo(r io.Reader) (*Meminfo, error) {
  203. var m Meminfo
  204. s := bufio.NewScanner(r)
  205. for s.Scan() {
  206. fields := strings.Fields(s.Text())
  207. var val, valBytes uint64
  208. val, err := strconv.ParseUint(fields[1], 0, 64)
  209. if err != nil {
  210. return nil, err
  211. }
  212. switch len(fields) {
  213. case 2:
  214. // No unit present, use the parsed the value as bytes directly.
  215. valBytes = val
  216. case 3:
  217. // Unit present in optional 3rd field, convert it to
  218. // bytes. The only unit supported within the Linux
  219. // kernel is `kB`.
  220. if fields[2] != "kB" {
  221. return nil, fmt.Errorf("%w: Unsupported unit in optional 3rd field %q", ErrFileParse, fields[2])
  222. }
  223. valBytes = 1024 * val
  224. default:
  225. return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text())
  226. }
  227. switch fields[0] {
  228. case "MemTotal:":
  229. m.MemTotal = &val
  230. m.MemTotalBytes = &valBytes
  231. case "MemFree:":
  232. m.MemFree = &val
  233. m.MemFreeBytes = &valBytes
  234. case "MemAvailable:":
  235. m.MemAvailable = &val
  236. m.MemAvailableBytes = &valBytes
  237. case "Buffers:":
  238. m.Buffers = &val
  239. m.BuffersBytes = &valBytes
  240. case "Cached:":
  241. m.Cached = &val
  242. m.CachedBytes = &valBytes
  243. case "SwapCached:":
  244. m.SwapCached = &val
  245. m.SwapCachedBytes = &valBytes
  246. case "Active:":
  247. m.Active = &val
  248. m.ActiveBytes = &valBytes
  249. case "Inactive:":
  250. m.Inactive = &val
  251. m.InactiveBytes = &valBytes
  252. case "Active(anon):":
  253. m.ActiveAnon = &val
  254. m.ActiveAnonBytes = &valBytes
  255. case "Inactive(anon):":
  256. m.InactiveAnon = &val
  257. m.InactiveAnonBytes = &valBytes
  258. case "Active(file):":
  259. m.ActiveFile = &val
  260. m.ActiveFileBytes = &valBytes
  261. case "Inactive(file):":
  262. m.InactiveFile = &val
  263. m.InactiveFileBytes = &valBytes
  264. case "Unevictable:":
  265. m.Unevictable = &val
  266. m.UnevictableBytes = &valBytes
  267. case "Mlocked:":
  268. m.Mlocked = &val
  269. m.MlockedBytes = &valBytes
  270. case "SwapTotal:":
  271. m.SwapTotal = &val
  272. m.SwapTotalBytes = &valBytes
  273. case "SwapFree:":
  274. m.SwapFree = &val
  275. m.SwapFreeBytes = &valBytes
  276. case "Dirty:":
  277. m.Dirty = &val
  278. m.DirtyBytes = &valBytes
  279. case "Writeback:":
  280. m.Writeback = &val
  281. m.WritebackBytes = &valBytes
  282. case "AnonPages:":
  283. m.AnonPages = &val
  284. m.AnonPagesBytes = &valBytes
  285. case "Mapped:":
  286. m.Mapped = &val
  287. m.MappedBytes = &valBytes
  288. case "Shmem:":
  289. m.Shmem = &val
  290. m.ShmemBytes = &valBytes
  291. case "Slab:":
  292. m.Slab = &val
  293. m.SlabBytes = &valBytes
  294. case "SReclaimable:":
  295. m.SReclaimable = &val
  296. m.SReclaimableBytes = &valBytes
  297. case "SUnreclaim:":
  298. m.SUnreclaim = &val
  299. m.SUnreclaimBytes = &valBytes
  300. case "KernelStack:":
  301. m.KernelStack = &val
  302. m.KernelStackBytes = &valBytes
  303. case "PageTables:":
  304. m.PageTables = &val
  305. m.PageTablesBytes = &valBytes
  306. case "NFS_Unstable:":
  307. m.NFSUnstable = &val
  308. m.NFSUnstableBytes = &valBytes
  309. case "Bounce:":
  310. m.Bounce = &val
  311. m.BounceBytes = &valBytes
  312. case "WritebackTmp:":
  313. m.WritebackTmp = &val
  314. m.WritebackTmpBytes = &valBytes
  315. case "CommitLimit:":
  316. m.CommitLimit = &val
  317. m.CommitLimitBytes = &valBytes
  318. case "Committed_AS:":
  319. m.CommittedAS = &val
  320. m.CommittedASBytes = &valBytes
  321. case "VmallocTotal:":
  322. m.VmallocTotal = &val
  323. m.VmallocTotalBytes = &valBytes
  324. case "VmallocUsed:":
  325. m.VmallocUsed = &val
  326. m.VmallocUsedBytes = &valBytes
  327. case "VmallocChunk:":
  328. m.VmallocChunk = &val
  329. m.VmallocChunkBytes = &valBytes
  330. case "Percpu:":
  331. m.Percpu = &val
  332. m.PercpuBytes = &valBytes
  333. case "HardwareCorrupted:":
  334. m.HardwareCorrupted = &val
  335. m.HardwareCorruptedBytes = &valBytes
  336. case "AnonHugePages:":
  337. m.AnonHugePages = &val
  338. m.AnonHugePagesBytes = &valBytes
  339. case "ShmemHugePages:":
  340. m.ShmemHugePages = &val
  341. m.ShmemHugePagesBytes = &valBytes
  342. case "ShmemPmdMapped:":
  343. m.ShmemPmdMapped = &val
  344. m.ShmemPmdMappedBytes = &valBytes
  345. case "CmaTotal:":
  346. m.CmaTotal = &val
  347. m.CmaTotalBytes = &valBytes
  348. case "CmaFree:":
  349. m.CmaFree = &val
  350. m.CmaFreeBytes = &valBytes
  351. case "HugePages_Total:":
  352. m.HugePagesTotal = &val
  353. case "HugePages_Free:":
  354. m.HugePagesFree = &val
  355. case "HugePages_Rsvd:":
  356. m.HugePagesRsvd = &val
  357. case "HugePages_Surp:":
  358. m.HugePagesSurp = &val
  359. case "Hugepagesize:":
  360. m.Hugepagesize = &val
  361. m.HugepagesizeBytes = &valBytes
  362. case "DirectMap4k:":
  363. m.DirectMap4k = &val
  364. m.DirectMap4kBytes = &valBytes
  365. case "DirectMap2M:":
  366. m.DirectMap2M = &val
  367. m.DirectMap2MBytes = &valBytes
  368. case "DirectMap1G:":
  369. m.DirectMap1G = &val
  370. m.DirectMap1GBytes = &valBytes
  371. }
  372. }
  373. return &m, nil
  374. }