feat: implement PSS (Proportional Set Size) for accurate real memory tracking
This commit is contained in:
@@ -10,6 +10,29 @@ use tauri::State;
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
// --- Helper for Real Memory (PSS) on Linux ---
|
||||||
|
|
||||||
|
fn get_pss(pid: u32) -> Option<u64> {
|
||||||
|
// PSS (Proportional Set Size) is the most accurate "real" memory metric.
|
||||||
|
// It counts private memory + proportional share of shared libraries.
|
||||||
|
// smaps_rollup is a fast way to get this on modern Linux kernels.
|
||||||
|
let path = format!("/proc/{}/smaps_rollup", pid);
|
||||||
|
if let Ok(contents) = fs::read_to_string(path) {
|
||||||
|
for line in contents.lines() {
|
||||||
|
if line.starts_with("Pss:") {
|
||||||
|
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||||
|
if parts.len() >= 2 {
|
||||||
|
if let Ok(kb) = parts[1].parse::<u64>() {
|
||||||
|
return Some(kb * 1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
// --- Data Structures ---
|
// --- Data Structures ---
|
||||||
|
|
||||||
@@ -139,12 +162,13 @@ fn get_system_stats(
|
|||||||
sys.processes().iter()
|
sys.processes().iter()
|
||||||
.map(|(pid, process)| {
|
.map(|(pid, process)| {
|
||||||
let pid_u32 = pid.as_u32();
|
let pid_u32 = pid.as_u32();
|
||||||
|
let memory = get_pss(pid_u32).unwrap_or_else(|| process.memory());
|
||||||
ProcessStats {
|
ProcessStats {
|
||||||
pid: pid_u32,
|
pid: pid_u32,
|
||||||
parent_pid: process.parent().map(|p| p.as_u32()),
|
parent_pid: process.parent().map(|p| p.as_u32()),
|
||||||
name: process.name().to_string_lossy().to_string(),
|
name: process.name().to_string_lossy().to_string(),
|
||||||
cpu_usage: process.cpu_usage(),
|
cpu_usage: process.cpu_usage(),
|
||||||
memory: process.memory(),
|
memory,
|
||||||
status: format!("{:?}", process.status()),
|
status: format!("{:?}", process.status()),
|
||||||
user_id: process.user_id().map(|uid| uid.to_string()),
|
user_id: process.user_id().map(|uid| uid.to_string()),
|
||||||
is_syspulse: is_descendant_of(pid_u32, self_pid, &sys),
|
is_syspulse: is_descendant_of(pid_u32, self_pid, &sys),
|
||||||
@@ -159,12 +183,13 @@ fn get_system_stats(
|
|||||||
processes = sys.processes().iter()
|
processes = sys.processes().iter()
|
||||||
.map(|(pid, process)| {
|
.map(|(pid, process)| {
|
||||||
let pid_u32 = pid.as_u32();
|
let pid_u32 = pid.as_u32();
|
||||||
|
let memory = get_pss(pid_u32).unwrap_or_else(|| process.memory());
|
||||||
ProcessStats {
|
ProcessStats {
|
||||||
pid: pid_u32,
|
pid: pid_u32,
|
||||||
parent_pid: process.parent().map(|p| p.as_u32()),
|
parent_pid: process.parent().map(|p| p.as_u32()),
|
||||||
name: process.name().to_string_lossy().to_string(),
|
name: process.name().to_string_lossy().to_string(),
|
||||||
cpu_usage: process.cpu_usage(),
|
cpu_usage: process.cpu_usage(),
|
||||||
memory: process.memory(),
|
memory,
|
||||||
status: format!("{:?}", process.status()),
|
status: format!("{:?}", process.status()),
|
||||||
user_id: process.user_id().map(|uid| uid.to_string()),
|
user_id: process.user_id().map(|uid| uid.to_string()),
|
||||||
is_syspulse: is_descendant_of(pid_u32, self_pid, &sys),
|
is_syspulse: is_descendant_of(pid_u32, self_pid, &sys),
|
||||||
|
|||||||
@@ -580,8 +580,8 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 bg-surface0/50 border-t border-surface1 text-[9px] text-overlay1 font-medium italic flex items-center gap-2">
|
<div className="p-4 bg-surface0/50 border-t border-surface1 text-[9px] text-overlay1 font-medium italic flex items-center gap-2">
|
||||||
<AlertTriangle size={10} />
|
<Shield size={10} className="text-blue" />
|
||||||
<span>Memory is Resident Set Size (RSS). Summed totals may exceed physical RAM due to shared segments.</span>
|
<span>Memory is Proportional Set Size (PSS). It includes private memory plus a proportional share of shared libraries, providing an accurate sum of total system impact.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user