diff --git a/mem/mem_darwin.go b/mem/mem_darwin.go index 56655958..33147bba 100644 --- a/mem/mem_darwin.go +++ b/mem/mem_darwin.go @@ -2,58 +2,13 @@ package mem -/* -#include -*/ -import "C" - import ( - "fmt" "strconv" "strings" - "syscall" - "unsafe" "github.com/shirou/gopsutil/internal/common" ) -// VirtualMemory returns VirtualmemoryStat. -func VirtualMemory() (*VirtualMemoryStat, error) { - count := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT) - var vmstat C.vm_statistics_data_t - - status := C.host_statistics(C.host_t(C.mach_host_self()), - C.HOST_VM_INFO, - C.host_info_t(unsafe.Pointer(&vmstat)), - &count) - - if status != C.KERN_SUCCESS { - return nil, fmt.Errorf("host_statistics error=%d", status) - } - - totalCount := vmstat.wire_count + - vmstat.active_count + - vmstat.inactive_count + - vmstat.free_count - - availableCount := vmstat.inactive_count + vmstat.free_count - usedPercent := 100 * float64(totalCount-availableCount) / float64(totalCount) - - usedCount := totalCount - vmstat.free_count - - pageSize := uint64(syscall.Getpagesize()) - return &VirtualMemoryStat{ - Total: pageSize * uint64(totalCount), - Available: pageSize * uint64(availableCount), - Used: pageSize * uint64(usedCount), - UsedPercent: usedPercent, - Free: pageSize * uint64(vmstat.free_count), - Active: pageSize * uint64(vmstat.active_count), - Inactive: pageSize * uint64(vmstat.inactive_count), - Wired: pageSize * uint64(vmstat.wire_count), - }, nil -} - // SwapMemory returns swapinfo. func SwapMemory() (*SwapMemoryStat, error) { var ret *SwapMemoryStat diff --git a/mem/mem_darwin_cgo.go b/mem/mem_darwin_cgo.go new file mode 100644 index 00000000..1d085281 --- /dev/null +++ b/mem/mem_darwin_cgo.go @@ -0,0 +1,52 @@ +// +build darwin +// +build cgo + +package mem + +/* +#include +*/ +import "C" + +import ( + "fmt" + "syscall" + "unsafe" +) + +// VirtualMemory returns VirtualmemoryStat. +func VirtualMemory() (*VirtualMemoryStat, error) { + count := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT) + var vmstat C.vm_statistics_data_t + + status := C.host_statistics(C.host_t(C.mach_host_self()), + C.HOST_VM_INFO, + C.host_info_t(unsafe.Pointer(&vmstat)), + &count) + + if status != C.KERN_SUCCESS { + return nil, fmt.Errorf("host_statistics error=%d", status) + } + + totalCount := vmstat.wire_count + + vmstat.active_count + + vmstat.inactive_count + + vmstat.free_count + + availableCount := vmstat.inactive_count + vmstat.free_count + usedPercent := 100 * float64(totalCount-availableCount) / float64(totalCount) + + usedCount := totalCount - vmstat.free_count + + pageSize := uint64(syscall.Getpagesize()) + return &VirtualMemoryStat{ + Total: pageSize * uint64(totalCount), + Available: pageSize * uint64(availableCount), + Used: pageSize * uint64(usedCount), + UsedPercent: usedPercent, + Free: pageSize * uint64(vmstat.free_count), + Active: pageSize * uint64(vmstat.active_count), + Inactive: pageSize * uint64(vmstat.inactive_count), + Wired: pageSize * uint64(vmstat.wire_count), + }, nil +} diff --git a/mem/mem_darwin_nocgo.go b/mem/mem_darwin_nocgo.go new file mode 100644 index 00000000..d1bd4f65 --- /dev/null +++ b/mem/mem_darwin_nocgo.go @@ -0,0 +1,90 @@ +// +build darwin +// +build !cgo + +package mem + +import ( + "os/exec" + "strconv" + "strings" + "syscall" + + "github.com/shirou/gopsutil/internal/common" +) + +// Runs vm_stat and returns Free and inactive pages +func getVMStat(vms *VirtualMemoryStat) error { + out, err := exec.Command("vm_stat").Output() + if err != nil { + return err + } + return parseVMStat(string(out), vms) +} + +func parseVMStat(out string, vms *VirtualMemoryStat) error { + var err error + + lines := strings.Split(out, "\n") + pagesize := uint64(syscall.Getpagesize()) + for _, line := range lines { + fields := strings.Split(line, ":") + if len(fields) < 2 { + continue + } + key := strings.TrimSpace(fields[0]) + value := strings.Trim(fields[1], " .") + switch key { + case "Pages free": + free, e := strconv.ParseUint(value, 10, 64) + if e != nil { + err = e + } + vms.Free = free * pagesize + case "Pages inactive": + inactive, e := strconv.ParseUint(value, 10, 64) + if e != nil { + err = e + } + vms.Inactive = inactive * pagesize + case "Pages active": + active, e := strconv.ParseUint(value, 10, 64) + if e != nil { + err = e + } + vms.Active = active * pagesize + case "Pages wired down": + wired, e := strconv.ParseUint(value, 10, 64) + if e != nil { + err = e + } + vms.Wired = wired * pagesize + } + } + return err +} + +// VirtualMemory returns VirtualmemoryStat. +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) + if err != nil { + return nil, err + } + err = getVMStat(ret) + if err != nil { + return nil, err + } + + 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 + + return ret, nil +} diff --git a/mem/mem_darwin_test.go b/mem/mem_darwin_test.go index cf10ea82..0f2ea3a9 100644 --- a/mem/mem_darwin_test.go +++ b/mem/mem_darwin_test.go @@ -14,9 +14,12 @@ func TestVirtualMemoryDarwin(t *testing.T) { assert.True(t, v.Total > 0) + assert.Equal(t, v.Total, v.Active+v.Inactive+v.Free+v.Wired) + 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) assert.True(t, v.Used < v.Total)