mirror of
https://github.com/shirou/gopsutil.git
synced 2025-05-10 19:29:14 +08:00
Merge pull request #160 from walles/walles/vmtest
Document + add tests for for mem.VirtualMemory()
This commit is contained in:
commit
1d09f7a4e9
46
mem/mem.go
46
mem/mem.go
@ -4,18 +4,44 @@ import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Memory usage statistics. Total, Available and Used contain numbers of bytes
|
||||
// for human consumption.
|
||||
//
|
||||
// The other fields in this struct contain kernel specific values.
|
||||
type VirtualMemoryStat struct {
|
||||
Total uint64 `json:"total"`
|
||||
Available uint64 `json:"available"`
|
||||
Used uint64 `json:"used"`
|
||||
// Total amount of RAM on this system
|
||||
Total uint64 `json:"total"`
|
||||
|
||||
// RAM available for programs to allocate
|
||||
//
|
||||
// This value is computed from the kernel specific values.
|
||||
Available uint64 `json:"available"`
|
||||
|
||||
// RAM used by programs
|
||||
//
|
||||
// This value is computed from the kernel specific values.
|
||||
Used uint64 `json:"used"`
|
||||
|
||||
// Percentage of RAM used by programs
|
||||
//
|
||||
// This value is computed from the kernel specific values.
|
||||
UsedPercent float64 `json:"used_percent"`
|
||||
Free uint64 `json:"free"`
|
||||
Active uint64 `json:"active"`
|
||||
Inactive uint64 `json:"inactive"`
|
||||
Buffers uint64 `json:"buffers"`
|
||||
Cached uint64 `json:"cached"`
|
||||
Wired uint64 `json:"wired"`
|
||||
Shared uint64 `json:"shared"`
|
||||
|
||||
// This is the kernel's notion of free memory; RAM chips whose bits nobody
|
||||
// cares about the value of right now. For a human consumable number,
|
||||
// Available is what you really want.
|
||||
Free uint64 `json:"free"`
|
||||
|
||||
// OS X / BSD specific numbers:
|
||||
// http://www.macyourself.com/2010/02/17/what-is-free-wired-active-and-inactive-system-memory-ram/
|
||||
Active uint64 `json:"active"`
|
||||
Inactive uint64 `json:"inactive"`
|
||||
Wired uint64 `json:"wired"`
|
||||
|
||||
// Linux specific numbers
|
||||
// https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s2-proc-meminfo.html
|
||||
Buffers uint64 `json:"buffers"`
|
||||
Cached uint64 `json:"cached"`
|
||||
}
|
||||
|
||||
type SwapMemoryStat struct {
|
||||
|
@ -3,12 +3,29 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func getHwMemsize() (uint64, error) {
|
||||
totalString, err := syscall.Sysctl("hw.memsize")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// syscall.sysctl() helpfully assumes the result is a null-terminated string and
|
||||
// removes the last byte of the result if it's 0 :/
|
||||
totalString += "\x00"
|
||||
|
||||
total := uint64(binary.LittleEndian.Uint64([]byte(totalString)))
|
||||
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// SwapMemory returns swapinfo.
|
||||
func SwapMemory() (*SwapMemoryStat, error) {
|
||||
var ret *SwapMemoryStat
|
||||
|
@ -28,19 +28,20 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
return nil, fmt.Errorf("host_statistics error=%d", status)
|
||||
}
|
||||
|
||||
totalCount := vmstat.wire_count +
|
||||
vmstat.active_count +
|
||||
vmstat.inactive_count +
|
||||
vmstat.free_count
|
||||
pageSize := uint64(syscall.Getpagesize())
|
||||
total, err := getHwMemsize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
totalCount := C.natural_t(total / pageSize)
|
||||
|
||||
availableCount := vmstat.inactive_count + vmstat.free_count
|
||||
usedPercent := 100 * float64(totalCount-availableCount) / float64(totalCount)
|
||||
|
||||
usedCount := totalCount - vmstat.free_count
|
||||
usedCount := totalCount - availableCount
|
||||
|
||||
pageSize := uint64(syscall.Getpagesize())
|
||||
return &VirtualMemoryStat{
|
||||
Total: pageSize * uint64(totalCount),
|
||||
Total: total,
|
||||
Available: pageSize * uint64(availableCount),
|
||||
Used: pageSize * uint64(usedCount),
|
||||
UsedPercent: usedPercent,
|
||||
|
@ -8,8 +8,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// Runs vm_stat and returns Free and inactive pages
|
||||
@ -67,11 +65,7 @@ func parseVMStat(out string, vms *VirtualMemoryStat) error {
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
ret := &VirtualMemoryStat{}
|
||||
|
||||
t, err := common.DoSysctrl("hw.memsize")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, err := strconv.ParseUint(t[0], 10, 64)
|
||||
total, err := getHwMemsize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -83,8 +77,8 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
ret.Available = ret.Free + ret.Inactive
|
||||
ret.Total = total
|
||||
|
||||
ret.Used = ret.Total - ret.Free
|
||||
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = 100 * float64(ret.Used) / float64(ret.Total)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -12,13 +15,16 @@ func TestVirtualMemoryDarwin(t *testing.T) {
|
||||
v, err := VirtualMemory()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, v.Total > 0)
|
||||
|
||||
assert.Equal(t, v.Total, v.Active+v.Inactive+v.Free+v.Wired)
|
||||
outBytes, err := exec.Command("/usr/sbin/sysctl", "hw.memsize").Output()
|
||||
assert.Nil(t, err)
|
||||
outString := string(outBytes)
|
||||
outString = strings.TrimSpace(outString)
|
||||
outParts := strings.Split(outString, " ")
|
||||
actualTotal, err := strconv.ParseInt(outParts[1], 10, 64)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, uint64(actualTotal), v.Total)
|
||||
|
||||
assert.True(t, v.Available > 0)
|
||||
assert.True(t, v.Available < v.Total)
|
||||
assert.Equal(t, v.Available, v.Total-v.Wired-v.Active, "%v", v)
|
||||
assert.Equal(t, v.Available, v.Free+v.Inactive, "%v", v)
|
||||
|
||||
assert.True(t, v.Used > 0)
|
||||
|
@ -79,8 +79,8 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
}
|
||||
|
||||
ret.Available = ret.Inactive + ret.Cached + ret.Free
|
||||
ret.Used = ret.Active + ret.Wired + ret.Cached
|
||||
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
if !memavail {
|
||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||
}
|
||||
ret.Used = ret.Total - ret.Free
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||
|
||||
return ret, nil
|
||||
|
@ -3,6 +3,8 @@ package mem
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVirtual_memory(t *testing.T) {
|
||||
@ -14,6 +16,21 @@ func TestVirtual_memory(t *testing.T) {
|
||||
if v == empty {
|
||||
t.Errorf("error %v", v)
|
||||
}
|
||||
|
||||
assert.True(t, v.Total > 0)
|
||||
assert.True(t, v.Available > 0)
|
||||
assert.True(t, v.Used > 0)
|
||||
|
||||
assert.Equal(t, v.Total, v.Available+v.Used,
|
||||
"Total should be computable from available + used: %v", v)
|
||||
|
||||
assert.True(t, v.Free > 0)
|
||||
assert.True(t, v.Available > v.Free,
|
||||
"Free should be a subset of Available: %v", v)
|
||||
|
||||
assert.InDelta(t, v.UsedPercent,
|
||||
100*float64(v.Used)/float64(v.Total), 0.1,
|
||||
"UsedPercent should be how many percent of Total is Used: %v", v)
|
||||
}
|
||||
|
||||
func TestSwap_memory(t *testing.T) {
|
||||
@ -35,7 +52,7 @@ func TestVirtualMemoryStat_String(t *testing.T) {
|
||||
UsedPercent: 30.1,
|
||||
Free: 40,
|
||||
}
|
||||
e := `{"total":10,"available":20,"used":30,"used_percent":30.1,"free":40,"active":0,"inactive":0,"buffers":0,"cached":0,"wired":0,"shared":0}`
|
||||
e := `{"total":10,"available":20,"used":30,"used_percent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"buffers":0,"cached":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("VirtualMemoryStat string is invalid: %v", v)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user