Skip to content

Commit 17a4b8d

Browse files
committed
Refactor memory
1 parent 72c60db commit 17a4b8d

9 files changed

Lines changed: 251 additions & 70 deletions

common/memory/memory.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@ package memory
33
import "runtime"
44

55
func Total() uint64 {
6-
if nativeAvailable {
7-
return usageNative()
8-
}
9-
return Inuse()
6+
return totalNative()
107
}
118

12-
func Inuse() uint64 {
13-
var memStats runtime.MemStats
14-
runtime.ReadMemStats(&memStats)
15-
return memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased
9+
func TotalAvailable() bool {
10+
return totalAvailable()
1611
}
1712

1813
func Available() uint64 {
1914
return availableNative()
2015
}
2116

22-
func AvailableSupported() bool {
23-
return availableNativeSupported()
17+
func AvailableAvailable() bool {
18+
return availableAvailable()
19+
}
20+
21+
func Inuse() uint64 {
22+
var memStats runtime.MemStats
23+
runtime.ReadMemStats(&memStats)
24+
return memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased
2425
}

common/memory/memory_available_darwin.go

Lines changed: 0 additions & 36 deletions
This file was deleted.

common/memory/memory_available_stub.go

Lines changed: 0 additions & 11 deletions
This file was deleted.

common/memory/memory_darwin.go

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,59 @@
11
package memory
22

33
// #include <mach/mach.h>
4+
// #include <stddef.h>
5+
// #include <dlfcn.h>
6+
//
7+
// typedef size_t (*proc_available_memory_func)(void);
8+
// static int resolved = 0;
9+
// static proc_available_memory_func fn = NULL;
10+
//
11+
// static void resolve_available_memory() {
12+
// if (!resolved) {
13+
// fn = (proc_available_memory_func)dlsym(RTLD_DEFAULT, "os_proc_available_memory");
14+
// resolved = 1;
15+
// }
16+
// }
17+
//
18+
// static size_t get_available_memory(int *supported) {
19+
// resolve_available_memory();
20+
// if (fn) {
21+
// *supported = 1;
22+
// return fn();
23+
// }
24+
// *supported = 0;
25+
// return 0;
26+
// }
27+
//
28+
// static int is_available_memory_supported() {
29+
// resolve_available_memory();
30+
// return fn != NULL;
31+
// }
432
import "C"
533
import "unsafe"
634

7-
const nativeAvailable = true
8-
9-
func usageNative() uint64 {
10-
var memoryUsageInByte uint64
35+
func totalNative() uint64 {
1136
var vmInfo C.task_vm_info_data_t
1237
var count C.mach_msg_type_number_t = C.TASK_VM_INFO_COUNT
13-
var kernelReturn C.kern_return_t = C.task_info(C.vm_map_t(C.mach_task_self_), C.TASK_VM_INFO, (*C.integer_t)(unsafe.Pointer(&vmInfo)), &count)
14-
if kernelReturn == C.KERN_SUCCESS {
15-
memoryUsageInByte = uint64(vmInfo.phys_footprint)
38+
if C.task_info(C.vm_map_t(C.mach_task_self_), C.TASK_VM_INFO, (*C.integer_t)(unsafe.Pointer(&vmInfo)), &count) == C.KERN_SUCCESS {
39+
return uint64(vmInfo.phys_footprint)
40+
}
41+
return 0
42+
}
43+
44+
func totalAvailable() bool {
45+
return true
46+
}
47+
48+
func availableNative() uint64 {
49+
var supported C.int
50+
result := C.get_available_memory(&supported)
51+
if supported == 0 {
52+
return 0
1653
}
17-
return memoryUsageInByte
54+
return uint64(result)
55+
}
56+
57+
func availableAvailable() bool {
58+
return C.is_available_memory_supported() != 0
1859
}
Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,41 @@ import (
88
"strings"
99
)
1010

11-
func availableNativeSupported() bool {
12-
return true
11+
var pageSize = uint64(os.Getpagesize())
12+
13+
func totalNative() uint64 {
14+
fd, err := os.Open("/proc/self/statm")
15+
if err != nil {
16+
return 0
17+
}
18+
defer fd.Close()
19+
var buf [128]byte
20+
n, _ := fd.Read(buf[:])
21+
if n == 0 {
22+
return 0
23+
}
24+
i := 0
25+
for i < n && buf[i] != ' ' {
26+
i++
27+
}
28+
i++
29+
var rss uint64
30+
for i < n && buf[i] >= '0' && buf[i] <= '9' {
31+
rss = rss*10 + uint64(buf[i]-'0')
32+
i++
33+
}
34+
return rss * pageSize
35+
}
36+
37+
func totalAvailable() bool {
38+
fd, err := os.Open("/proc/self/statm")
39+
if err != nil {
40+
return false
41+
}
42+
defer fd.Close()
43+
var buf [1]byte
44+
n, _ := fd.Read(buf[:])
45+
return n > 0
1346
}
1447

1548
func availableNative() uint64 {
@@ -20,6 +53,19 @@ func availableNative() uint64 {
2053
return procMemAvailable()
2154
}
2255

56+
func availableAvailable() bool {
57+
_, ok := cgroupAvailable()
58+
if ok {
59+
return true
60+
}
61+
fd, err := os.Open("/proc/meminfo")
62+
if err != nil {
63+
return false
64+
}
65+
fd.Close()
66+
return true
67+
}
68+
2369
func cgroupAvailable() (uint64, bool) {
2470
max, err := readCgroupUint("/sys/fs/cgroup/memory.max")
2571
if err == nil && max != math.MaxUint64 {

common/memory/memory_stub.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
//go:build (darwin && !cgo) || !darwin
1+
//go:build (darwin && !cgo) || (!darwin && !linux && !windows)
22

33
package memory
44

5-
const nativeAvailable = false
5+
func totalNative() uint64 {
6+
return 0
7+
}
8+
9+
func totalAvailable() bool {
10+
return false
11+
}
612

7-
func usageNative() uint64 {
13+
func availableNative() uint64 {
814
return 0
915
}
16+
17+
func availableAvailable() bool {
18+
return false
19+
}

common/memory/memory_windows.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package memory
2+
3+
import (
4+
"unsafe"
5+
6+
"golang.org/x/sys/windows"
7+
)
8+
9+
func totalNative() uint64 {
10+
var mem processMemoryCounters
11+
mem.cb = uint32(unsafe.Sizeof(mem))
12+
err := getProcessMemoryInfo(windows.CurrentProcess(), &mem, mem.cb)
13+
if err != nil {
14+
return 0
15+
}
16+
return uint64(mem.workingSetSize)
17+
}
18+
19+
func totalAvailable() bool {
20+
return true
21+
}
22+
23+
func availableNative() uint64 {
24+
var mem memoryStatusEx
25+
mem.dwLength = uint32(unsafe.Sizeof(mem))
26+
err := globalMemoryStatusEx(&mem)
27+
if err != nil {
28+
return 0
29+
}
30+
return mem.ullAvailPhys
31+
}
32+
33+
func availableAvailable() bool {
34+
return true
35+
}

common/memory/syscall_windows.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package memory
2+
3+
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
4+
5+
type processMemoryCounters struct {
6+
cb uint32
7+
pageFaultCount uint32
8+
peakWorkingSetSize uintptr
9+
workingSetSize uintptr
10+
quotaPeakPagedPoolUsage uintptr
11+
quotaPagedPoolUsage uintptr
12+
quotaPeakNonPagedPoolUsage uintptr
13+
quotaNonPagedPoolUsage uintptr
14+
pagefileUsage uintptr
15+
peakPagefileUsage uintptr
16+
}
17+
18+
type memoryStatusEx struct {
19+
dwLength uint32
20+
dwMemoryLoad uint32
21+
ullTotalPhys uint64
22+
ullAvailPhys uint64
23+
ullTotalPageFile uint64
24+
ullAvailPageFile uint64
25+
ullTotalVirtual uint64
26+
ullAvailVirtual uint64
27+
ullAvailExtendedVirtual uint64
28+
}
29+
30+
// https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo
31+
//sys getProcessMemoryInfo(process windows.Handle, ppsmemCounters *processMemoryCounters, cb uint32) (err error) = kernel32.K32GetProcessMemoryInfo
32+
33+
// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex
34+
//sys globalMemoryStatusEx(lpBuffer *memoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx

common/memory/zsyscall_windows.go

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)