mem_linux.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // +build linux
  2. package mem
  3. import (
  4. "context"
  5. "strconv"
  6. "strings"
  7. "github.com/shirou/gopsutil/internal/common"
  8. "golang.org/x/sys/unix"
  9. )
  10. func VirtualMemory() (*VirtualMemoryStat, error) {
  11. return VirtualMemoryWithContext(context.Background())
  12. }
  13. func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
  14. filename := common.HostProc("meminfo")
  15. lines, _ := common.ReadLines(filename)
  16. // flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
  17. memavail := false
  18. ret := &VirtualMemoryStat{}
  19. for _, line := range lines {
  20. fields := strings.Split(line, ":")
  21. if len(fields) != 2 {
  22. continue
  23. }
  24. key := strings.TrimSpace(fields[0])
  25. value := strings.TrimSpace(fields[1])
  26. value = strings.Replace(value, " kB", "", -1)
  27. t, err := strconv.ParseUint(value, 10, 64)
  28. if err != nil {
  29. return ret, err
  30. }
  31. switch key {
  32. case "MemTotal":
  33. ret.Total = t * 1024
  34. case "MemFree":
  35. ret.Free = t * 1024
  36. case "MemAvailable":
  37. memavail = true
  38. ret.Available = t * 1024
  39. case "Buffers":
  40. ret.Buffers = t * 1024
  41. case "Cached":
  42. ret.Cached = t * 1024
  43. case "Active":
  44. ret.Active = t * 1024
  45. case "Inactive":
  46. ret.Inactive = t * 1024
  47. case "Writeback":
  48. ret.Writeback = t * 1024
  49. case "WritebackTmp":
  50. ret.WritebackTmp = t * 1024
  51. case "Dirty":
  52. ret.Dirty = t * 1024
  53. case "Shmem":
  54. ret.Shared = t * 1024
  55. case "Slab":
  56. ret.Slab = t * 1024
  57. case "PageTables":
  58. ret.PageTables = t * 1024
  59. case "SwapCached":
  60. ret.SwapCached = t * 1024
  61. case "CommitLimit":
  62. ret.CommitLimit = t * 1024
  63. case "Committed_AS":
  64. ret.CommittedAS = t * 1024
  65. case "HighTotal":
  66. ret.HighTotal = t * 1024
  67. case "HighFree":
  68. ret.HighFree = t * 1024
  69. case "LowTotal":
  70. ret.LowTotal = t * 1024
  71. case "LowFree":
  72. ret.LowFree = t * 1024
  73. case "SwapTotal":
  74. ret.SwapTotal = t * 1024
  75. case "SwapFree":
  76. ret.SwapFree = t * 1024
  77. case "Mapped":
  78. ret.Mapped = t * 1024
  79. case "VmallocTotal":
  80. ret.VMallocTotal = t * 1024
  81. case "VmallocUsed":
  82. ret.VMallocUsed = t * 1024
  83. case "VmallocChunk":
  84. ret.VMallocChunk = t * 1024
  85. case "HugePages_Total":
  86. ret.HugePagesTotal = t
  87. case "HugePages_Free":
  88. ret.HugePagesFree = t
  89. case "Hugepagesize":
  90. ret.HugePageSize = t * 1024
  91. }
  92. }
  93. if !memavail {
  94. ret.Available = ret.Free + ret.Buffers + ret.Cached
  95. }
  96. ret.Used = ret.Total - ret.Free - ret.Buffers - ret.Cached
  97. ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
  98. return ret, nil
  99. }
  100. func SwapMemory() (*SwapMemoryStat, error) {
  101. return SwapMemoryWithContext(context.Background())
  102. }
  103. func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
  104. sysinfo := &unix.Sysinfo_t{}
  105. if err := unix.Sysinfo(sysinfo); err != nil {
  106. return nil, err
  107. }
  108. ret := &SwapMemoryStat{
  109. Total: uint64(sysinfo.Totalswap) * uint64(sysinfo.Unit),
  110. Free: uint64(sysinfo.Freeswap) * uint64(sysinfo.Unit),
  111. }
  112. ret.Used = ret.Total - ret.Free
  113. //check Infinity
  114. if ret.Total != 0 {
  115. ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0
  116. } else {
  117. ret.UsedPercent = 0
  118. }
  119. filename := common.HostProc("vmstat")
  120. lines, _ := common.ReadLines(filename)
  121. for _, l := range lines {
  122. fields := strings.Fields(l)
  123. if len(fields) < 2 {
  124. continue
  125. }
  126. switch fields[0] {
  127. case "pswpin":
  128. value, err := strconv.ParseUint(fields[1], 10, 64)
  129. if err != nil {
  130. continue
  131. }
  132. ret.Sin = value * 4 * 1024
  133. case "pswpout":
  134. value, err := strconv.ParseUint(fields[1], 10, 64)
  135. if err != nil {
  136. continue
  137. }
  138. ret.Sout = value * 4 * 1024
  139. }
  140. }
  141. return ret, nil
  142. }