sysutil/
ram.rs

1use std::fs::read_dir;
2use crate::utils::{*};
3
4/// Contains all information about RAM
5#[derive(Debug)]
6pub struct RAM {
7    pub size: ByteSize,
8    pub usage: f32,
9    pub frequency: Option<usize>,
10    pub busWidth: Option<usize>
11}
12
13impl RAM {
14    pub fn new() -> RAM {
15        RAM {
16            size: ramSize(),
17            usage: ramUsage(),
18            frequency: ramFrequency(),
19            busWidth: ramBusWidth()
20        }
21    }
22}
23
24/// Returns current RAM usage in percentage
25pub fn ramUsage() -> f32 {
26    linuxCheck();
27
28    let content = readFile("/proc/meminfo");
29
30    let mut memTotal = "";
31    let mut memAvailable = "";
32
33    for element in content.split('\n') {
34        if element.contains("MemTotal") {
35            memTotal = element;
36        } else if element.contains("MemAvailable") {
37            memAvailable = element;
38        }
39    }
40
41    let uMemTotal = {
42        let mut total = 0_usize;
43        for element in memTotal.split(" ") {
44            if element != "MemTotal:" && !element.is_empty() {
45                total = element.parse::<usize>().unwrap();
46                break;
47            }
48        }
49        total
50    };
51
52    let uMemAvailable = {
53        let mut available = 0_usize;
54        for element in memAvailable.split(" ") {
55            if element != "MemAvailable:" && !element.is_empty() {
56                available = element.parse::<usize>().unwrap();
57                break;
58            }
59        }
60        available
61    };
62
63    return 100_f32 - uMemAvailable as f32 * 100_f32 / uMemTotal as f32;
64}
65
66/// Returns RAM size using the `ByteSize` data structure
67pub fn ramSize() -> ByteSize {
68    linuxCheck();
69
70    let content = readFile("/proc/meminfo");
71    let mut memTotal = "";
72
73    for element in content.split('\n') {
74        if element.contains("MemTotal") {
75            memTotal = element;
76        }
77    }
78
79    let uMemTotal = {
80        let mut total = 0_usize;
81        for element in memTotal.split(" ") {
82            if element != "MemTotal:" && !element.is_empty() {
83                total = element.parse::<usize>().unwrap();
84                break;
85            }
86        }
87        total
88    };
89
90    ByteSize::fromBytes(uMemTotal * 1000)
91}
92
93/// Returns RAM frequency in MT/s
94pub fn ramFrequency() -> Option<usize> {
95    let kfdTopologyNodes = "/sys/class/kfd/kfd/topology/nodes/";
96    for dir in read_dir(kfdTopologyNodes).unwrap() {
97        let path = dir.unwrap().path();
98        let directory = path.to_str().unwrap();
99
100        let content = readFile(format!("{}/properties", directory));
101        let mut isCpu = false;
102
103        for line in content.split("\n") {
104            if line.contains("cpu_cores_count") {
105                let splitedLine = line.split(" ").collect::<Vec<&str>>();
106                match splitedLine.last() {
107                    Some(cores) => {
108                        if cores.parse::<usize>().unwrap() != 0 {
109                            isCpu = true;
110                        }
111                    },
112
113                    None => {
114                        continue
115                    }
116                }
117            }
118
119            if isCpu {
120                break
121            }
122        }
123
124        if isCpu {
125            let memBanksInfo = readFile(format!("{}/mem_banks/0/properties", directory));
126            let mut frequencyLine = String::new();
127
128            for line in memBanksInfo.split("\n") {
129                if line.contains("mem_clk_max") {
130                    frequencyLine = line.to_string();
131                    break
132                }
133            }
134
135            let frequency = {
136                let binding = frequencyLine.split(" ").collect::<Vec<&str>>();
137                let last = binding.last().unwrap();
138                last.parse::<usize>().unwrap()
139            };
140
141            return Some(frequency);
142        }
143    }
144
145    return None;
146}
147
148/// Returns RAM bus width in bits
149pub fn ramBusWidth() -> Option<usize> {
150    let kfdTopologyNodes = "/sys/class/kfd/kfd/topology/nodes/";
151    for dir in read_dir(kfdTopologyNodes).unwrap() {
152        let path = dir.unwrap().path();
153        let directory = path.to_str().unwrap();
154
155        let content = readFile(format!("{}/properties", directory));
156        let mut isCpu = false;
157
158        for line in content.split("\n") {
159            if line.contains("cpu_cores_count") {
160                let splitedLine = line.split(" ").collect::<Vec<&str>>();
161                match splitedLine.last() {
162                    Some(cores) => {
163                        if cores.parse::<usize>().unwrap() != 0 {
164                            isCpu = true;
165                        }
166                    },
167
168                    None => {
169                        continue
170                    }
171                }
172            }
173
174            if isCpu {
175                break
176            }
177        }
178
179        if isCpu {
180            let memBanksInfo = readFile(format!("{}/mem_banks/0/properties", directory));
181            let mut widthLine = String::new();
182
183            for line in memBanksInfo.split("\n") {
184                if line.contains("width") {
185                    widthLine = line.to_string();
186                    break
187                }
188            }
189
190            let width = {
191                let binding = widthLine.split(" ").collect::<Vec<&str>>();
192                let last = binding.last().unwrap();
193                last.parse::<usize>().unwrap()
194            };
195
196            return Some(width);
197        }
198    }
199
200    return None;
201}