Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 1 | // Copyright 2022, The Android Open Source Project |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
Seungjae Yoo | 46fc8ba | 2022-10-19 14:02:08 +0900 | [diff] [blame] | 15 | use anyhow::{bail, Result}; |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 16 | use libc::{sysconf, _SC_CLK_TCK}; |
Seungjae Yoo | 46fc8ba | 2022-10-19 14:02:08 +0900 | [diff] [blame] | 17 | use std::fs::File; |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 18 | use std::io::{BufRead, BufReader}; |
| 19 | |
| 20 | const MILLIS_PER_SEC: i64 = 1000; |
| 21 | |
| 22 | pub struct CpuTime { |
| 23 | pub user: i64, |
| 24 | pub nice: i64, |
| 25 | pub sys: i64, |
| 26 | pub idle: i64, |
| 27 | } |
| 28 | |
| 29 | pub struct MemInfo { |
| 30 | pub total: i64, |
| 31 | pub free: i64, |
| 32 | pub available: i64, |
| 33 | pub buffer: i64, |
| 34 | pub cached: i64, |
| 35 | } |
| 36 | |
| 37 | // Get CPU time information from /proc/stat |
| 38 | // |
| 39 | // /proc/stat example(omitted): |
| 40 | // cpu 24790952 21104390 10771070 10480973587 1700955 0 410931 0 316532 0 |
| 41 | // cpu0 169636 141307 61153 81785791 9605 0 183524 0 1345 0 |
| 42 | // cpu1 182431 198327 68273 81431817 10445 0 32392 0 2616 0 |
| 43 | // cpu2 183209 174917 68591 81933935 12239 0 10042 0 2415 0 |
| 44 | // cpu3 183413 177758 69908 81927474 13354 0 5853 0 2491 0 |
| 45 | // intr 7913477443 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 |
| 46 | // ctxt 10326710014 |
| 47 | // btime 1664123605 |
| 48 | // processes 9225712 |
| 49 | // procs_running 1 |
| 50 | // procs_blocked 0 |
| 51 | // softirq 2683914305 14595298 304837101 1581 327291100 16397051 0 208857783 1024640365 787932 786506094 |
| 52 | // |
| 53 | // expected output: |
| 54 | // user: 24790952 |
| 55 | // nice: 21104390 |
| 56 | // sys: 10771070 |
| 57 | // idle: 10480973587 |
| 58 | pub fn get_cpu_time() -> Result<CpuTime> { |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 59 | let mut proc_stat = BufReader::new(File::open("/proc/stat")?); |
| 60 | let mut line = String::new(); |
| 61 | proc_stat.read_line(&mut line)?; |
Seungjae Yoo | 46fc8ba | 2022-10-19 14:02:08 +0900 | [diff] [blame] | 62 | let data_list: Vec<_> = line.split_whitespace().filter_map(|s| s.parse::<i64>().ok()).collect(); |
| 63 | if data_list.len() < 4 { |
| 64 | bail!("Failed to extract numeric values in /proc/stat :\n{}", line); |
| 65 | } |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 66 | |
| 67 | let ticks_per_sec = unsafe { sysconf(_SC_CLK_TCK) } as i64; |
| 68 | let cpu_time = CpuTime { |
Seungjae Yoo | 46fc8ba | 2022-10-19 14:02:08 +0900 | [diff] [blame] | 69 | user: data_list[0] * MILLIS_PER_SEC / ticks_per_sec, |
| 70 | nice: data_list[1] * MILLIS_PER_SEC / ticks_per_sec, |
| 71 | sys: data_list[2] * MILLIS_PER_SEC / ticks_per_sec, |
| 72 | idle: data_list[3] * MILLIS_PER_SEC / ticks_per_sec, |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 73 | }; |
| 74 | Ok(cpu_time) |
| 75 | } |
| 76 | |
| 77 | // Get memory information from /proc/meminfo |
| 78 | // |
| 79 | // /proc/meminfo example(omitted): |
| 80 | // MemTotal: 263742736 kB |
| 81 | // MemFree: 37144204 kB |
| 82 | // MemAvailable: 249168700 kB |
| 83 | // Buffers: 10231296 kB |
| 84 | // Cached: 189502836 kB |
| 85 | // SwapCached: 113848 kB |
| 86 | // Active: 132266424 kB |
| 87 | // Inactive: 73587504 kB |
| 88 | // Active(anon): 1455240 kB |
| 89 | // Inactive(anon): 6993584 kB |
| 90 | // Active(file): 130811184 kB |
| 91 | // Inactive(file): 66593920 kB |
| 92 | // Unevictable: 56436 kB |
| 93 | // Mlocked: 56436 kB |
| 94 | // SwapTotal: 255123452 kB |
| 95 | // SwapFree: 254499068 kB |
| 96 | // Dirty: 596 kB |
| 97 | // Writeback: 0 kB |
| 98 | // AnonPages: 5295864 kB |
| 99 | // Mapped: 3512608 kB |
| 100 | // |
| 101 | // expected output: |
| 102 | // total: 263742736 |
| 103 | // free: 37144204 |
| 104 | // available: 249168700 |
| 105 | // buffer: 10231296 |
| 106 | // cached: 189502836 |
| 107 | pub fn get_mem_info() -> Result<MemInfo> { |
Seungjae Yoo | 46fc8ba | 2022-10-19 14:02:08 +0900 | [diff] [blame] | 108 | let mut proc_stat = BufReader::new(File::open("/proc/meminfo")?); |
| 109 | let mut lines = String::new(); |
| 110 | for _ in 0..5 { |
| 111 | proc_stat.read_line(&mut lines)?; |
| 112 | } |
| 113 | let data_list: Vec<_> = |
| 114 | lines.split_whitespace().filter_map(|s| s.parse::<i64>().ok()).collect(); |
| 115 | if data_list.len() != 5 { |
| 116 | bail!("Failed to extract numeric values in /proc/meminfo :\n{}", lines); |
| 117 | } |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 118 | |
| 119 | let mem_info = MemInfo { |
Seungjae Yoo | 46fc8ba | 2022-10-19 14:02:08 +0900 | [diff] [blame] | 120 | total: data_list[0], |
| 121 | free: data_list[1], |
| 122 | available: data_list[2], |
| 123 | buffer: data_list[3], |
| 124 | cached: data_list[4], |
Seungjae Yoo | fd9a062 | 2022-10-14 10:01:29 +0900 | [diff] [blame] | 125 | }; |
| 126 | Ok(mem_info) |
| 127 | } |