memory_linux.go raw
1 //go:build linux && !(js && wasm)
2
3 package ratelimit
4
5 import (
6 "bufio"
7 "os"
8 "strconv"
9 "strings"
10 )
11
12 // ReadProcessMemoryStats reads memory statistics from /proc/self/status.
13 // This provides accurate RSS (Resident Set Size) information on Linux,
14 // including the breakdown between shared and anonymous memory.
15 func ReadProcessMemoryStats() ProcessMemoryStats {
16 stats := ProcessMemoryStats{}
17
18 file, err := os.Open("/proc/self/status")
19 if err != nil {
20 // Fallback to runtime stats if /proc is not available
21 return readProcessMemoryStatsFallback()
22 }
23 defer file.Close()
24
25 scanner := bufio.NewScanner(file)
26 for scanner.Scan() {
27 line := scanner.Text()
28 fields := strings.Fields(line)
29 if len(fields) < 2 {
30 continue
31 }
32
33 key := strings.TrimSuffix(fields[0], ":")
34 valueStr := fields[1]
35
36 value, err := strconv.ParseUint(valueStr, 10, 64)
37 if err != nil {
38 continue
39 }
40
41 // Values in /proc/self/status are in kB
42 valueBytes := value * 1024
43
44 switch key {
45 case "VmRSS":
46 stats.VmRSS = valueBytes
47 case "RssShmem":
48 stats.RssShmem = valueBytes
49 case "RssAnon":
50 stats.RssAnon = valueBytes
51 case "VmHWM":
52 stats.VmHWM = valueBytes
53 }
54 }
55
56 // If we didn't get VmRSS, fall back to runtime stats
57 if stats.VmRSS == 0 {
58 return readProcessMemoryStatsFallback()
59 }
60
61 return stats
62 }
63