vendor tsgo

This commit is contained in:
2026-07-09 16:50:43 -04:00
parent c06ea2e5a4
commit 98978e4930
5804 changed files with 1556156 additions and 101 deletions

View File

@@ -0,0 +1,127 @@
//go:build darwin
package memory
import (
"bufio"
"context"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"time"
"unsafe"
"golang.org/x/sys/unix"
)
// Get memory statistics
func Get() (*Stats, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Reference: man 1 vm_stat
cmd := exec.CommandContext(ctx, "vm_stat")
out, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
memory, err := collectMemoryStats(out)
if err != nil {
// it is needed to cleanup the process, but its result is not needed.
go cmd.Wait() //nolint:errcheck
return nil, err
}
if err := cmd.Wait(); err != nil {
return nil, err
}
// Reference: sys/sysctl.h, man 3 sysctl, sysctl vm.swapusage
ret, err := unix.SysctlRaw("vm.swapusage")
if err != nil {
return nil, fmt.Errorf("failed in sysctl vm.swapusage: %s", err)
}
swap, err := collectSwapStats(ret)
if err != nil {
return nil, err
}
memory.SwapTotal = swap.Total
memory.SwapUsed = swap.Used
memory.SwapFree = swap.Avail
return memory, nil
}
// Stats represents memory statistics for darwin
type Stats struct {
Total, Used, Cached, Free, Active, Inactive, SwapTotal, SwapUsed, SwapFree uint64
}
// References:
// - https://support.apple.com/guide/activity-monitor/view-memory-usage-actmntr1004/10.14/mac/11.0
// - https://opensource.apple.com/source/system_cmds/system_cmds-880.60.2/vm_stat.tproj/
func collectMemoryStats(out io.Reader) (*Stats, error) {
scanner := bufio.NewScanner(out)
if !scanner.Scan() {
return nil, fmt.Errorf("failed to scan output of vm_stat")
}
line := scanner.Text()
var pageSize uint64
if _, err := fmt.Sscanf(line, "Mach Virtual Memory Statistics: (page size of %d bytes)", &pageSize); err != nil {
return nil, fmt.Errorf("unexpected output of vm_stat: %s", line)
}
var memory Stats
var speculative, wired, purgeable, fileBacked, compressed uint64
memStats := map[string]*uint64{
"Pages free": &memory.Free,
"Pages active": &memory.Active,
"Pages inactive": &memory.Inactive,
"Pages speculative": &speculative,
"Pages wired down": &wired,
"Pages purgeable": &purgeable,
"File-backed pages": &fileBacked,
"Pages occupied by compressor": &compressed,
}
for scanner.Scan() {
line := scanner.Text()
i := strings.IndexRune(line, ':')
if i < 0 {
continue
}
if ptr := memStats[line[:i]]; ptr != nil {
val := strings.TrimRight(strings.TrimSpace(line[i+1:]), ".")
if v, err := strconv.ParseUint(val, 10, 64); err == nil {
*ptr = v * pageSize
}
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("scan error for vm_stat: %s", err)
}
memory.Cached = purgeable + fileBacked
memory.Used = wired + compressed + memory.Active + memory.Inactive + speculative - memory.Cached
memory.Total = memory.Used + memory.Cached + memory.Free
return &memory, nil
}
// xsw_usage in sys/sysctl.h
type swapUsage struct {
Total uint64
Avail uint64
Used uint64
Pagesize int32
Encrypted bool
}
func collectSwapStats(out []byte) (*swapUsage, error) {
if len(out) != 32 {
return nil, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", out, len(out))
}
return (*swapUsage)(unsafe.Pointer(&out[0])), nil
}

View File

@@ -0,0 +1,118 @@
//go:build freebsd
package memory
import (
"bufio"
"context"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"time"
"unsafe"
"golang.org/x/sys/unix"
)
// Get memory statistics
func Get() (*Stats, error) {
return collectMemoryStats()
}
// Stats represents memory statistics for freebsd
type Stats struct {
Total, Used, Cached, Free, Active, Inactive, Wired,
SwapTotal, SwapUsed, SwapFree uint64
}
type memStat struct {
name string
ptr *uint64
scale *uint64
}
func collectMemoryStats() (*Stats, error) {
var pageSize uint64
one := uint64(1)
var memory Stats
memStats := []memStat{
{"vm.stats.vm.v_page_size", &pageSize, &one},
{"hw.physmem", &memory.Total, &one},
{"vm.stats.vm.v_cache_count", &memory.Cached, &pageSize},
{"vm.stats.vm.v_free_count", &memory.Free, &pageSize},
{"vm.stats.vm.v_active_count", &memory.Active, &pageSize},
{"vm.stats.vm.v_inactive_count", &memory.Inactive, &pageSize},
{"vm.stats.vm.v_wire_count", &memory.Wired, &pageSize},
}
for _, stat := range memStats {
ret, err := unix.SysctlRaw(stat.name)
if err != nil {
return nil, fmt.Errorf("failed in sysctl %s: %s", stat.name, err)
}
if len(ret) == 8 {
*stat.ptr = *(*uint64)(unsafe.Pointer(&ret[0])) * *stat.scale
} else if len(ret) == 4 {
*stat.ptr = uint64(*(*uint32)(unsafe.Pointer(&ret[0]))) * *stat.scale
} else {
return nil, fmt.Errorf("failed in sysctl %s: %s", stat.name, err)
}
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// collect swap statistics from swapinfo command
cmd := exec.CommandContext(ctx, "swapinfo", "-k")
out, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
memory.SwapTotal, memory.SwapUsed, err = collectSwapStats(out)
if err != nil {
go cmd.Wait() // nolint
return nil, err
}
if err := cmd.Wait(); err != nil {
return nil, err
}
memory.Used = memory.Total - memory.Free - memory.Cached - memory.Inactive
memory.SwapFree = memory.SwapTotal - memory.SwapUsed
return &memory, nil
}
func collectSwapStats(out io.Reader) (uint64, uint64, error) {
scanner := bufio.NewScanner(out)
if !scanner.Scan() {
return 0, 0, fmt.Errorf("failed to scan output of swapinfo")
}
line := scanner.Text()
if !strings.HasPrefix(line, "Device") {
return 0, 0, fmt.Errorf("unexpected output of swapinfo: %s", line)
}
var total, used uint64
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 5 {
continue
}
if v, err := strconv.ParseUint(fields[1], 10, 64); err == nil {
total += v * 1024
}
if v, err := strconv.ParseUint(fields[2], 10, 64); err == nil {
used += v * 1024
}
}
return total, used, nil
}

View File

@@ -0,0 +1,84 @@
//go:build linux
package memory
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
// Get memory statistics
func Get() (*Stats, error) {
// Reference: man 5 proc, Documentation/filesystems/proc.txt in Linux source code
file, err := os.Open("/proc/meminfo")
if err != nil {
return nil, err
}
defer file.Close() // nolint
return collectMemoryStats(file)
}
// Stats represents memory statistics for linux
type Stats struct {
Total, Used, Buffers, Cached, Free, Available, Active, Inactive,
SwapTotal, SwapUsed, SwapCached, SwapFree, Mapped, Shmem, Slab,
PageTables, Committed, VmallocUsed uint64
MemAvailableEnabled bool
}
func collectMemoryStats(out io.Reader) (*Stats, error) {
scanner := bufio.NewScanner(out)
var memory Stats
memStats := map[string]*uint64{
"MemTotal": &memory.Total,
"MemFree": &memory.Free,
"MemAvailable": &memory.Available,
"Buffers": &memory.Buffers,
"Cached": &memory.Cached,
"Active": &memory.Active,
"Inactive": &memory.Inactive,
"SwapCached": &memory.SwapCached,
"SwapTotal": &memory.SwapTotal,
"SwapFree": &memory.SwapFree,
"Mapped": &memory.Mapped,
"Shmem": &memory.Shmem,
"Slab": &memory.Slab,
"PageTables": &memory.PageTables,
"Committed_AS": &memory.Committed,
"VmallocUsed": &memory.VmallocUsed,
}
for scanner.Scan() {
line := scanner.Text()
i := strings.IndexRune(line, ':')
if i < 0 {
continue
}
fld := line[:i]
if ptr := memStats[fld]; ptr != nil {
val := strings.TrimSpace(strings.TrimRight(line[i+1:], "kB"))
if v, err := strconv.ParseUint(val, 10, 64); err == nil {
*ptr = v * 1024
}
if fld == "MemAvailable" {
memory.MemAvailableEnabled = true
}
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("scan error for /proc/meminfo: %s", err)
}
memory.SwapUsed = memory.SwapTotal - memory.SwapFree
if memory.MemAvailableEnabled {
memory.Used = memory.Total - memory.Available
} else {
memory.Used = memory.Total - memory.Free - memory.Buffers - memory.Cached
}
return &memory, nil
}

View File

@@ -0,0 +1,18 @@
//go:build !linux && !darwin && !windows && !freebsd
package memory
import (
"fmt"
"runtime"
)
// Get memory statistics
func Get() (*Stats, error) {
return nil, fmt.Errorf("memory statistics not implemented for: %s", runtime.GOOS)
}
// Stats represents memory statistics
type Stats struct {
Total, Used, Cached, Free, Active, Inactive, SwapTotal, SwapUsed, SwapFree uint64
}

View File

@@ -0,0 +1,53 @@
//go:build windows
package memory
import (
"fmt"
"syscall"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
globalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx")
)
// Get memory statistics
func Get() (*Stats, error) {
var memoryStatus memoryStatusEx
memoryStatus.Length = uint32(unsafe.Sizeof(memoryStatus))
ret, _, err := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memoryStatus)))
if ret == 0 {
return nil, fmt.Errorf("failed in GlobalMemoryStatusEx: %s", err)
}
var memory Stats
memory.Free = memoryStatus.AvailPhys
memory.Total = memoryStatus.TotalPhys
memory.Used = memory.Total - memory.Free
memory.PageFileTotal = memoryStatus.TotalPageFile
memory.PageFileFree = memoryStatus.AvailPageFile
memory.VirtualTotal = memoryStatus.TotalVirtual
memory.VirtualFree = memoryStatus.AvailVirtual
return &memory, nil
}
type memoryStatusEx struct {
Length uint32
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
// Stats represents memory statistics for Windows
type Stats struct {
Total, Used, Free, PageFileTotal, PageFileFree, VirtualTotal, VirtualFree uint64
}