v / vlib / runtime / used_memory_linux.c.v
46 lines · 44 sloc · 1.57 KB · a15a9cc1239be10c443a08c68950f15bb54929a1
Raw
1module runtime
2
3import os
4
5// used_memory retrieves the current physical memory usage of the process.
6@[manualfree]
7pub fn used_memory() !u64 {
8 buffer := [1024]u8{}
9 pc := unsafe { &buffer[0] }
10 // see https://man7.org/linux/man-pages/man5/proc_pid_stat.5.html for a detailed description of the format.
11 // Here is an example:
12 // 699989 (test_program) R 178038 699989 178038 34816 699989 0 102 0 0 0 0 0 0 0 20 0 1 0 84188763 5726208 129 18446744073709551615 93824992239616 93824992257073 140737488345056 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 93824992275088 93824992276672 93824992280576 140737488346201 140737488346221 140737488346221 140737488351211 0
13 // => read the file in the fixed buffer, search to after the `)` to skip the variable name part, then scan till the `129` RSS value, and then convert it from pages to bytes.
14 mut f := os.open_file('/proc/self/stat', 'r')!
15 defer { f.close() }
16 read := f.read_into_ptr(pc, buffer.len)!
17 if read <= 0 {
18 return error('could not read from /proc/self/stat')
19 }
20 mut c := 0
21 unsafe {
22 // scan to after the process name (`comm`) field:
23 for c < buffer.len && *pc != `)` {
24 pc++
25 c++
26 }
27 mut spaces := 0
28 // the following fields, are space separated numbers, skip past them to the `rss` field:
29 for c < buffer.len && spaces < 22 {
30 if *pc == ` ` {
31 spaces++
32 }
33 pc++
34 c++
35 }
36 mut ndigits := 0
37 // scan till the end of the `rss` field:
38 for c < buffer.len && *(pc + ndigits) != ` ` {
39 ndigits++
40 c++
41 }
42 rss_pages := pc.vstring_with_len(ndigits).u64()
43 page_size := C.sysconf(C._SC_PAGESIZE)
44 return u64(rss_pages * page_size)
45 }
46}
47