pkg.re/essentialkaos/ek@v12.36.0+incompatible/system/process/process_memory.go (about)

     1  // +build linux
     2  
     3  package process
     4  
     5  // ////////////////////////////////////////////////////////////////////////////////// //
     6  //                                                                                    //
     7  //                         Copyright (c) 2021 ESSENTIAL KAOS                          //
     8  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     9  //                                                                                    //
    10  // ////////////////////////////////////////////////////////////////////////////////// //
    11  
    12  import (
    13  	"bufio"
    14  	"errors"
    15  	"os"
    16  	"strconv"
    17  
    18  	"pkg.re/essentialkaos/ek.v12/strutil"
    19  )
    20  
    21  // ////////////////////////////////////////////////////////////////////////////////// //
    22  
    23  // MemInfo contains process memory usage stats
    24  type MemInfo struct {
    25  	VmPeak uint64 `json:"peak"` // Peak virtual memory size
    26  	VmSize uint64 `json:"size"` // Virtual memory size
    27  	VmLck  uint64 `json:"lck"`  // Locked memory size
    28  	VmPin  uint64 `json:"pin"`  // Pinned memory size (since Linux 3.2)
    29  	VmHWM  uint64 `json:"hwm"`  // Peak resident set size ("high water mark")
    30  	VmRSS  uint64 `json:"rss"`  // Resident set size
    31  	VmData uint64 `json:"data"` // Size of data
    32  	VmStk  uint64 `json:"stk"`  // Size of stack
    33  	VmExe  uint64 `json:"exe"`  // Size of text segments
    34  	VmLib  uint64 `json:"lib"`  // Shared library code size
    35  	VmPTE  uint64 `json:"pte"`  // Page table entries size (since Linux 2.6.10)
    36  	VmSwap uint64 `json:"swap"` // Swap size
    37  }
    38  
    39  // ////////////////////////////////////////////////////////////////////////////////// //
    40  
    41  // codebeat:disable[LOC,ABC]
    42  
    43  // GetMemInfo returns info about process memory usage
    44  func GetMemInfo(pid int) (*MemInfo, error) {
    45  	fd, err := os.OpenFile(procFS+"/"+strconv.Itoa(pid)+"/status", os.O_RDONLY, 0)
    46  
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	defer fd.Close()
    52  
    53  	r := bufio.NewReader(fd)
    54  	s := bufio.NewScanner(r)
    55  
    56  	info := &MemInfo{}
    57  
    58  	for s.Scan() {
    59  		text := s.Text()
    60  
    61  		if len(text) < 2 || text[:2] != "Vm" {
    62  			continue
    63  		}
    64  
    65  		switch strutil.ReadField(text, 0, true) {
    66  		case "VmPeak:":
    67  			info.VmPeak, err = parseSize(strutil.ReadField(text, 1, true))
    68  		case "VmSize:":
    69  			info.VmSize, err = parseSize(strutil.ReadField(text, 1, true))
    70  		case "VmLck:":
    71  			info.VmLck, err = parseSize(strutil.ReadField(text, 1, true))
    72  		case "VmPin:":
    73  			info.VmPin, err = parseSize(strutil.ReadField(text, 1, true))
    74  		case "VmHWM:":
    75  			info.VmHWM, err = parseSize(strutil.ReadField(text, 1, true))
    76  		case "VmRSS:":
    77  			info.VmRSS, err = parseSize(strutil.ReadField(text, 1, true))
    78  		case "VmData:":
    79  			info.VmData, err = parseSize(strutil.ReadField(text, 1, true))
    80  		case "VmStk:":
    81  			info.VmStk, err = parseSize(strutil.ReadField(text, 1, true))
    82  		case "VmExe:":
    83  			info.VmExe, err = parseSize(strutil.ReadField(text, 1, true))
    84  		case "VmLib:":
    85  			info.VmLib, err = parseSize(strutil.ReadField(text, 1, true))
    86  		case "VmPTE:":
    87  			info.VmPTE, err = parseSize(strutil.ReadField(text, 1, true))
    88  		case "VmSwap:":
    89  			info.VmSwap, err = parseSize(strutil.ReadField(text, 1, true))
    90  		}
    91  
    92  		if err != nil {
    93  			return nil, errors.New("Can't parse status file for given process")
    94  		}
    95  	}
    96  
    97  	if info.VmPeak+info.VmSize == 0 {
    98  		return nil, errors.New("Can't parse status file for given process")
    99  	}
   100  
   101  	return info, nil
   102  }
   103  
   104  // codebeat:enable[LOC,ABC]
   105  
   106  // ////////////////////////////////////////////////////////////////////////////////// //
   107  
   108  // parseSize parse size in kB
   109  func parseSize(v string) (uint64, error) {
   110  	size, err := strconv.ParseUint(v, 10, 64)
   111  
   112  	if err != nil {
   113  		return 0, err
   114  	}
   115  
   116  	return size * 1024, nil
   117  }