feat: implement collapsible tree view with inclusive resource metrics and improved memory calculation
This commit is contained in:
@@ -3,17 +3,17 @@ name = "syspulse-rs"
|
||||
version = "0.1.0"
|
||||
description = "A professional Linux system profiler"
|
||||
authors = ["narl"]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.5.5" }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.10.2", features = [] }
|
||||
chrono = "0.4.43"
|
||||
env_logger = "0.11.9"
|
||||
log = "0.4.29"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
sysinfo = "0.38.2"
|
||||
chrono = "0.4.43"
|
||||
tauri = "2.10.2"
|
||||
tokio = { version = "1.49.0", features = ["full"] }
|
||||
log = "0.4.29"
|
||||
env_logger = "0.11.9"
|
||||
|
||||
@@ -241,7 +241,6 @@ fn stop_profiling(state: State<AppState>) -> Report {
|
||||
// 2. Aggregate RAW stats per PID
|
||||
struct PidStats {
|
||||
name: String,
|
||||
parent_pid: Option<u32>,
|
||||
history: Vec<ProcessHistoryPoint>,
|
||||
peak_cpu: f32,
|
||||
peak_mem: f32,
|
||||
@@ -256,7 +255,6 @@ fn stop_profiling(state: State<AppState>) -> Report {
|
||||
for proc in &snapshot.processes {
|
||||
let entry = pid_map.entry(proc.pid).or_insert_with(|| PidStats {
|
||||
name: proc.name.clone(),
|
||||
parent_pid: proc.parent_pid,
|
||||
history: Vec::new(),
|
||||
peak_cpu: 0.0,
|
||||
peak_mem: 0.0,
|
||||
@@ -320,7 +318,7 @@ fn stop_profiling(state: State<AppState>) -> Report {
|
||||
|
||||
let pids: Vec<u32> = nodes.keys().cloned().collect();
|
||||
for pid in pids {
|
||||
if let Some(&ppid) = child_to_parent.get(&pid) {
|
||||
if let Some(&_ppid) = child_to_parent.get(&pid) {
|
||||
// Already handled in recursive aggregation or linked below
|
||||
} else {
|
||||
root_pids.push(pid);
|
||||
@@ -328,23 +326,24 @@ fn stop_profiling(state: State<AppState>) -> Report {
|
||||
}
|
||||
|
||||
// 5. Recursive function to calculate inclusive stats and build tree
|
||||
fn build_node(pid: u32, nodes: &mut HashMap<u32, AggregatedProcess>, child_map: &HashMap<u32, Vec<u32>>) -> AggregatedProcess {
|
||||
let mut node = nodes.remove(&pid).unwrap();
|
||||
fn build_node(pid: u32, nodes: &mut HashMap<u32, AggregatedProcess>, child_map: &HashMap<u32, Vec<u32>>) -> Option<AggregatedProcess> {
|
||||
let mut node = nodes.remove(&pid)?;
|
||||
let children_pids = child_map.get(&pid).cloned().unwrap_or_default();
|
||||
|
||||
let mut inc_cpu = node.avg_cpu;
|
||||
let mut inc_mem = node.avg_memory_mb;
|
||||
|
||||
for c_pid in children_pids {
|
||||
let child_node = build_node(c_pid, nodes, child_map);
|
||||
if let Some(child_node) = build_node(c_pid, nodes, child_map) {
|
||||
inc_cpu += child_node.inclusive_avg_cpu;
|
||||
inc_mem += child_node.inclusive_avg_memory_mb;
|
||||
node.children.push(child_node);
|
||||
}
|
||||
}
|
||||
|
||||
node.inclusive_avg_cpu = inc_cpu;
|
||||
node.inclusive_avg_memory_mb = inc_mem;
|
||||
node
|
||||
Some(node)
|
||||
}
|
||||
|
||||
let mut child_map: HashMap<u32, Vec<u32>> = HashMap::new();
|
||||
@@ -354,8 +353,16 @@ fn stop_profiling(state: State<AppState>) -> Report {
|
||||
|
||||
let mut final_roots = Vec::new();
|
||||
for pid in root_pids {
|
||||
if nodes.contains_key(&pid) {
|
||||
final_roots.push(build_node(pid, &mut nodes, &child_map));
|
||||
if let Some(root_node) = build_node(pid, &mut nodes, &child_map) {
|
||||
final_roots.push(root_node);
|
||||
}
|
||||
}
|
||||
|
||||
// Include any remaining orphan nodes as roots (e.g. if parent info was missing in snapshots)
|
||||
let remaining_pids: Vec<u32> = nodes.keys().cloned().collect();
|
||||
for pid in remaining_pids {
|
||||
if let Some(node) = build_node(pid, &mut nodes, &child_map) {
|
||||
final_roots.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user