| 1 | module runtime |
| 2 | |
| 3 | import os |
| 4 | |
| 5 | // used_memory retrieves the current physical memory usage of the process. |
| 6 | @[manualfree] |
| 7 | pub 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 | |