123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // +build linux
- package mem
- import (
- "context"
- "strconv"
- "strings"
- "github.com/shirou/gopsutil/internal/common"
- "golang.org/x/sys/unix"
- )
- func VirtualMemory() (*VirtualMemoryStat, error) {
- return VirtualMemoryWithContext(context.Background())
- }
- func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
- filename := common.HostProc("meminfo")
- lines, _ := common.ReadLines(filename)
- // flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
- memavail := false
- ret := &VirtualMemoryStat{}
- for _, line := range lines {
- fields := strings.Split(line, ":")
- if len(fields) != 2 {
- continue
- }
- key := strings.TrimSpace(fields[0])
- value := strings.TrimSpace(fields[1])
- value = strings.Replace(value, " kB", "", -1)
- t, err := strconv.ParseUint(value, 10, 64)
- if err != nil {
- return ret, err
- }
- switch key {
- case "MemTotal":
- ret.Total = t * 1024
- case "MemFree":
- ret.Free = t * 1024
- case "MemAvailable":
- memavail = true
- ret.Available = t * 1024
- case "Buffers":
- ret.Buffers = t * 1024
- case "Cached":
- ret.Cached = t * 1024
- case "Active":
- ret.Active = t * 1024
- case "Inactive":
- ret.Inactive = t * 1024
- case "Writeback":
- ret.Writeback = t * 1024
- case "WritebackTmp":
- ret.WritebackTmp = t * 1024
- case "Dirty":
- ret.Dirty = t * 1024
- case "Shmem":
- ret.Shared = t * 1024
- case "Slab":
- ret.Slab = t * 1024
- case "PageTables":
- ret.PageTables = t * 1024
- case "SwapCached":
- ret.SwapCached = t * 1024
- case "CommitLimit":
- ret.CommitLimit = t * 1024
- case "Committed_AS":
- ret.CommittedAS = t * 1024
- case "HighTotal":
- ret.HighTotal = t * 1024
- case "HighFree":
- ret.HighFree = t * 1024
- case "LowTotal":
- ret.LowTotal = t * 1024
- case "LowFree":
- ret.LowFree = t * 1024
- case "SwapTotal":
- ret.SwapTotal = t * 1024
- case "SwapFree":
- ret.SwapFree = t * 1024
- case "Mapped":
- ret.Mapped = t * 1024
- case "VmallocTotal":
- ret.VMallocTotal = t * 1024
- case "VmallocUsed":
- ret.VMallocUsed = t * 1024
- case "VmallocChunk":
- ret.VMallocChunk = t * 1024
- case "HugePages_Total":
- ret.HugePagesTotal = t
- case "HugePages_Free":
- ret.HugePagesFree = t
- case "Hugepagesize":
- ret.HugePageSize = t * 1024
- }
- }
- if !memavail {
- ret.Available = ret.Free + ret.Buffers + ret.Cached
- }
- ret.Used = ret.Total - ret.Free - ret.Buffers - ret.Cached
- ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
- return ret, nil
- }
- func SwapMemory() (*SwapMemoryStat, error) {
- return SwapMemoryWithContext(context.Background())
- }
- func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
- sysinfo := &unix.Sysinfo_t{}
- if err := unix.Sysinfo(sysinfo); err != nil {
- return nil, err
- }
- ret := &SwapMemoryStat{
- Total: uint64(sysinfo.Totalswap) * uint64(sysinfo.Unit),
- Free: uint64(sysinfo.Freeswap) * uint64(sysinfo.Unit),
- }
- ret.Used = ret.Total - ret.Free
- //check Infinity
- if ret.Total != 0 {
- ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0
- } else {
- ret.UsedPercent = 0
- }
- filename := common.HostProc("vmstat")
- lines, _ := common.ReadLines(filename)
- for _, l := range lines {
- fields := strings.Fields(l)
- if len(fields) < 2 {
- continue
- }
- switch fields[0] {
- case "pswpin":
- value, err := strconv.ParseUint(fields[1], 10, 64)
- if err != nil {
- continue
- }
- ret.Sin = value * 4 * 1024
- case "pswpout":
- value, err := strconv.ParseUint(fields[1], 10, 64)
- if err != nil {
- continue
- }
- ret.Sout = value * 4 * 1024
- }
- }
- return ret, nil
- }
|