diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cb1ae27..56a7db5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -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" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a5f79cc..9e9d7e1 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -241,7 +241,6 @@ fn stop_profiling(state: State) -> Report { // 2. Aggregate RAW stats per PID struct PidStats { name: String, - parent_pid: Option, history: Vec, peak_cpu: f32, peak_mem: f32, @@ -256,7 +255,6 @@ fn stop_profiling(state: State) -> 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) -> Report { let pids: Vec = 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) -> Report { } // 5. Recursive function to calculate inclusive stats and build tree - fn build_node(pid: u32, nodes: &mut HashMap, child_map: &HashMap>) -> AggregatedProcess { - let mut node = nodes.remove(&pid).unwrap(); + fn build_node(pid: u32, nodes: &mut HashMap, child_map: &HashMap>) -> Option { + 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); - inc_cpu += child_node.inclusive_avg_cpu; - inc_mem += child_node.inclusive_avg_memory_mb; - node.children.push(child_node); + 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> = HashMap::new(); @@ -354,8 +353,16 @@ fn stop_profiling(state: State) -> 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 = nodes.keys().cloned().collect(); + for pid in remaining_pids { + if let Some(node) = build_node(pid, &mut nodes, &child_map) { + final_roots.push(node); } }