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 }