...

Source file src/github.com/prometheus/procfs/meminfo.go

Documentation: github.com/prometheus/procfs

     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  
    14  package procfs
    15  
    16  import (
    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.
    28  type 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  	Percpu            *uint64
   130  	HardwareCorrupted *uint64
   131  	AnonHugePages     *uint64
   132  	ShmemHugePages    *uint64
   133  	ShmemPmdMapped    *uint64
   134  	CmaTotal          *uint64
   135  	CmaFree           *uint64
   136  	HugePagesTotal    *uint64
   137  	HugePagesFree     *uint64
   138  	HugePagesRsvd     *uint64
   139  	HugePagesSurp     *uint64
   140  	Hugepagesize      *uint64
   141  	DirectMap4k       *uint64
   142  	DirectMap2M       *uint64
   143  	DirectMap1G       *uint64
   144  
   145  	// The struct fields below are the byte-normalized counterparts to the
   146  	// existing struct fields. Values are normalized using the optional
   147  	// unit field in the meminfo line.
   148  	MemTotalBytes          *uint64
   149  	MemFreeBytes           *uint64
   150  	MemAvailableBytes      *uint64
   151  	BuffersBytes           *uint64
   152  	CachedBytes            *uint64
   153  	SwapCachedBytes        *uint64
   154  	ActiveBytes            *uint64
   155  	InactiveBytes          *uint64
   156  	ActiveAnonBytes        *uint64
   157  	InactiveAnonBytes      *uint64
   158  	ActiveFileBytes        *uint64
   159  	InactiveFileBytes      *uint64
   160  	UnevictableBytes       *uint64
   161  	MlockedBytes           *uint64
   162  	SwapTotalBytes         *uint64
   163  	SwapFreeBytes          *uint64
   164  	DirtyBytes             *uint64
   165  	WritebackBytes         *uint64
   166  	AnonPagesBytes         *uint64
   167  	MappedBytes            *uint64
   168  	ShmemBytes             *uint64
   169  	SlabBytes              *uint64
   170  	SReclaimableBytes      *uint64
   171  	SUnreclaimBytes        *uint64
   172  	KernelStackBytes       *uint64
   173  	PageTablesBytes        *uint64
   174  	NFSUnstableBytes       *uint64
   175  	BounceBytes            *uint64
   176  	WritebackTmpBytes      *uint64
   177  	CommitLimitBytes       *uint64
   178  	CommittedASBytes       *uint64
   179  	VmallocTotalBytes      *uint64
   180  	VmallocUsedBytes       *uint64
   181  	VmallocChunkBytes      *uint64
   182  	PercpuBytes            *uint64
   183  	HardwareCorruptedBytes *uint64
   184  	AnonHugePagesBytes     *uint64
   185  	ShmemHugePagesBytes    *uint64
   186  	ShmemPmdMappedBytes    *uint64
   187  	CmaTotalBytes          *uint64
   188  	CmaFreeBytes           *uint64
   189  	HugepagesizeBytes      *uint64
   190  	DirectMap4kBytes       *uint64
   191  	DirectMap2MBytes       *uint64
   192  	DirectMap1GBytes       *uint64
   193  }
   194  
   195  // Meminfo returns an information about current kernel/system memory statistics.
   196  // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
   197  func (fs FS) Meminfo() (Meminfo, error) {
   198  	b, err := util.ReadFileNoStat(fs.proc.Path("meminfo"))
   199  	if err != nil {
   200  		return Meminfo{}, err
   201  	}
   202  
   203  	m, err := parseMemInfo(bytes.NewReader(b))
   204  	if err != nil {
   205  		return Meminfo{}, fmt.Errorf("%s: %w", ErrFileParse, err)
   206  	}
   207  
   208  	return *m, nil
   209  }
   210  
   211  func parseMemInfo(r io.Reader) (*Meminfo, error) {
   212  	var m Meminfo
   213  	s := bufio.NewScanner(r)
   214  	for s.Scan() {
   215  		fields := strings.Fields(s.Text())
   216  		var val, valBytes uint64
   217  
   218  		val, err := strconv.ParseUint(fields[1], 0, 64)
   219  		if err != nil {
   220  			return nil, err
   221  		}
   222  
   223  		switch len(fields) {
   224  		case 2:
   225  			// No unit present, use the parsed the value as bytes directly.
   226  			valBytes = val
   227  		case 3:
   228  			// Unit present in optional 3rd field, convert it to
   229  			// bytes. The only unit supported within the Linux
   230  			// kernel is `kB`.
   231  			if fields[2] != "kB" {
   232  				return nil, fmt.Errorf("%w: Unsupported unit in optional 3rd field %q", ErrFileParse, fields[2])
   233  			}
   234  
   235  			valBytes = 1024 * val
   236  
   237  		default:
   238  			return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text())
   239  		}
   240  
   241  		switch fields[0] {
   242  		case "MemTotal:":
   243  			m.MemTotal = &val
   244  			m.MemTotalBytes = &valBytes
   245  		case "MemFree:":
   246  			m.MemFree = &val
   247  			m.MemFreeBytes = &valBytes
   248  		case "MemAvailable:":
   249  			m.MemAvailable = &val
   250  			m.MemAvailableBytes = &valBytes
   251  		case "Buffers:":
   252  			m.Buffers = &val
   253  			m.BuffersBytes = &valBytes
   254  		case "Cached:":
   255  			m.Cached = &val
   256  			m.CachedBytes = &valBytes
   257  		case "SwapCached:":
   258  			m.SwapCached = &val
   259  			m.SwapCachedBytes = &valBytes
   260  		case "Active:":
   261  			m.Active = &val
   262  			m.ActiveBytes = &valBytes
   263  		case "Inactive:":
   264  			m.Inactive = &val
   265  			m.InactiveBytes = &valBytes
   266  		case "Active(anon):":
   267  			m.ActiveAnon = &val
   268  			m.ActiveAnonBytes = &valBytes
   269  		case "Inactive(anon):":
   270  			m.InactiveAnon = &val
   271  			m.InactiveAnonBytes = &valBytes
   272  		case "Active(file):":
   273  			m.ActiveFile = &val
   274  			m.ActiveFileBytes = &valBytes
   275  		case "Inactive(file):":
   276  			m.InactiveFile = &val
   277  			m.InactiveFileBytes = &valBytes
   278  		case "Unevictable:":
   279  			m.Unevictable = &val
   280  			m.UnevictableBytes = &valBytes
   281  		case "Mlocked:":
   282  			m.Mlocked = &val
   283  			m.MlockedBytes = &valBytes
   284  		case "SwapTotal:":
   285  			m.SwapTotal = &val
   286  			m.SwapTotalBytes = &valBytes
   287  		case "SwapFree:":
   288  			m.SwapFree = &val
   289  			m.SwapFreeBytes = &valBytes
   290  		case "Dirty:":
   291  			m.Dirty = &val
   292  			m.DirtyBytes = &valBytes
   293  		case "Writeback:":
   294  			m.Writeback = &val
   295  			m.WritebackBytes = &valBytes
   296  		case "AnonPages:":
   297  			m.AnonPages = &val
   298  			m.AnonPagesBytes = &valBytes
   299  		case "Mapped:":
   300  			m.Mapped = &val
   301  			m.MappedBytes = &valBytes
   302  		case "Shmem:":
   303  			m.Shmem = &val
   304  			m.ShmemBytes = &valBytes
   305  		case "Slab:":
   306  			m.Slab = &val
   307  			m.SlabBytes = &valBytes
   308  		case "SReclaimable:":
   309  			m.SReclaimable = &val
   310  			m.SReclaimableBytes = &valBytes
   311  		case "SUnreclaim:":
   312  			m.SUnreclaim = &val
   313  			m.SUnreclaimBytes = &valBytes
   314  		case "KernelStack:":
   315  			m.KernelStack = &val
   316  			m.KernelStackBytes = &valBytes
   317  		case "PageTables:":
   318  			m.PageTables = &val
   319  			m.PageTablesBytes = &valBytes
   320  		case "NFS_Unstable:":
   321  			m.NFSUnstable = &val
   322  			m.NFSUnstableBytes = &valBytes
   323  		case "Bounce:":
   324  			m.Bounce = &val
   325  			m.BounceBytes = &valBytes
   326  		case "WritebackTmp:":
   327  			m.WritebackTmp = &val
   328  			m.WritebackTmpBytes = &valBytes
   329  		case "CommitLimit:":
   330  			m.CommitLimit = &val
   331  			m.CommitLimitBytes = &valBytes
   332  		case "Committed_AS:":
   333  			m.CommittedAS = &val
   334  			m.CommittedASBytes = &valBytes
   335  		case "VmallocTotal:":
   336  			m.VmallocTotal = &val
   337  			m.VmallocTotalBytes = &valBytes
   338  		case "VmallocUsed:":
   339  			m.VmallocUsed = &val
   340  			m.VmallocUsedBytes = &valBytes
   341  		case "VmallocChunk:":
   342  			m.VmallocChunk = &val
   343  			m.VmallocChunkBytes = &valBytes
   344  		case "Percpu:":
   345  			m.Percpu = &val
   346  			m.PercpuBytes = &valBytes
   347  		case "HardwareCorrupted:":
   348  			m.HardwareCorrupted = &val
   349  			m.HardwareCorruptedBytes = &valBytes
   350  		case "AnonHugePages:":
   351  			m.AnonHugePages = &val
   352  			m.AnonHugePagesBytes = &valBytes
   353  		case "ShmemHugePages:":
   354  			m.ShmemHugePages = &val
   355  			m.ShmemHugePagesBytes = &valBytes
   356  		case "ShmemPmdMapped:":
   357  			m.ShmemPmdMapped = &val
   358  			m.ShmemPmdMappedBytes = &valBytes
   359  		case "CmaTotal:":
   360  			m.CmaTotal = &val
   361  			m.CmaTotalBytes = &valBytes
   362  		case "CmaFree:":
   363  			m.CmaFree = &val
   364  			m.CmaFreeBytes = &valBytes
   365  		case "HugePages_Total:":
   366  			m.HugePagesTotal = &val
   367  		case "HugePages_Free:":
   368  			m.HugePagesFree = &val
   369  		case "HugePages_Rsvd:":
   370  			m.HugePagesRsvd = &val
   371  		case "HugePages_Surp:":
   372  			m.HugePagesSurp = &val
   373  		case "Hugepagesize:":
   374  			m.Hugepagesize = &val
   375  			m.HugepagesizeBytes = &valBytes
   376  		case "DirectMap4k:":
   377  			m.DirectMap4k = &val
   378  			m.DirectMap4kBytes = &valBytes
   379  		case "DirectMap2M:":
   380  			m.DirectMap2M = &val
   381  			m.DirectMap2MBytes = &valBytes
   382  		case "DirectMap1G:":
   383  			m.DirectMap1G = &val
   384  			m.DirectMap1GBytes = &valBytes
   385  		}
   386  	}
   387  
   388  	return &m, nil
   389  }
   390  

View as plain text