1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-05-12 19:29:30 +08:00
shirou_gopsutil/mem/mem_freebsd.go
Steven Hartland 6450c60b61 Eliminate use of sysctl command on FreeBSD
In order to improve performance and help prevent crashes due to the outstanding fork crash bug:
https://github.com/golang/go/issues/15658

Replace string parsed values from the sysctl command with native reads of sysctl values using unix.SysctlRaw and unix.SysctlUint32.

This also merges OpenBSD and FreeBSD load implementations which are identical.
2017-10-05 08:45:56 +01:00

113 lines
2.4 KiB
Go

// +build freebsd
package mem
import (
"errors"
"os/exec"
"strconv"
"strings"
"golang.org/x/sys/unix"
)
func VirtualMemory() (*VirtualMemoryStat, error) {
pageSize, err := unix.SysctlUint32("vm.stats.vm.v_page_size")
if err != nil {
return nil, err
}
pageCount, err := unix.SysctlUint32("vm.stats.vm.v_page_count")
if err != nil {
return nil, err
}
free, err := unix.SysctlUint32("vm.stats.vm.v_free_count")
if err != nil {
return nil, err
}
active, err := unix.SysctlUint32("vm.stats.vm.v_active_count")
if err != nil {
return nil, err
}
inactive, err := unix.SysctlUint32("vm.stats.vm.v_inactive_count")
if err != nil {
return nil, err
}
cached, err := unix.SysctlUint32("vm.stats.vm.v_cache_count")
if err != nil {
return nil, err
}
buffers, err := unix.SysctlUint32("vfs.bufspace")
if err != nil {
return nil, err
}
wired, err := unix.SysctlUint32("vm.stats.vm.v_wire_count")
if err != nil {
return nil, err
}
p := uint64(pageSize)
ret := &VirtualMemoryStat{
Total: uint64(pageCount) * p,
Free: uint64(free) * p,
Active: uint64(active) * p,
Inactive: uint64(inactive) * p,
Cached: uint64(cached) * p,
Buffers: uint64(buffers),
Wired: uint64(wired) * p,
}
ret.Available = ret.Inactive + ret.Cached + ret.Free
ret.Used = ret.Total - ret.Available
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
return ret, nil
}
// Return swapinfo
// FreeBSD can have multiple swap devices. but use only first device
func SwapMemory() (*SwapMemoryStat, error) {
swapinfo, err := exec.LookPath("swapinfo")
if err != nil {
return nil, err
}
out, err := invoke.Command(swapinfo)
if err != nil {
return nil, err
}
for _, line := range strings.Split(string(out), "\n") {
values := strings.Fields(line)
// skip title line
if len(values) == 0 || values[0] == "Device" {
continue
}
u := strings.Replace(values[4], "%", "", 1)
total_v, err := strconv.ParseUint(values[1], 10, 64)
if err != nil {
return nil, err
}
used_v, err := strconv.ParseUint(values[2], 10, 64)
if err != nil {
return nil, err
}
free_v, err := strconv.ParseUint(values[3], 10, 64)
if err != nil {
return nil, err
}
up_v, err := strconv.ParseFloat(u, 64)
if err != nil {
return nil, err
}
return &SwapMemoryStat{
Total: total_v,
Used: used_v,
Free: free_v,
UsedPercent: up_v,
}, nil
}
return nil, errors.New("no swap devices found")
}