performance improvement: caching static info

This commit is contained in:
Abdenasser 2024-11-04 22:07:16 +01:00
parent cbcfbf8b10
commit d151579da5
3 changed files with 35 additions and 40 deletions

11
src-tauri/Cargo.lock generated
View File

@ -2016,7 +2016,6 @@ dependencies = [
"sysinfo", "sysinfo",
"tauri", "tauri",
"tauri-build", "tauri-build",
"users",
] ]
[[package]] [[package]]
@ -4347,16 +4346,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "users"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
dependencies = [
"libc",
"log",
]
[[package]] [[package]]
name = "utf-8" name = "utf-8"
version = "0.7.6" version = "0.7.6"

View File

@ -13,7 +13,6 @@ serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.5", features = ["api-all"] } tauri = { version = "1.5", features = ["api-all"] }
sysinfo = "0.29.0" sysinfo = "0.29.0"
users = "0.11"
[features] [features]
default = [ "custom-protocol" ] default = [ "custom-protocol" ]

View File

@ -3,10 +3,21 @@
use sysinfo::{CpuExt, SystemExt, ProcessExt, System, PidExt, ProcessStatus}; use sysinfo::{CpuExt, SystemExt, ProcessExt, System, PidExt, ProcessStatus};
use tauri::State; use tauri::State;
use std::sync::Mutex; use std::sync::Mutex;
use users::{Users, UsersCache}; use std::time;
use std::collections::HashMap;
use std::time::Instant;
struct AppState { struct AppState {
sys: Mutex<System>, sys: Mutex<System>,
process_cache: Mutex<HashMap<u32, ProcessStaticInfo>>,
last_update: Mutex<Instant>,
}
#[derive(Clone)]
struct ProcessStaticInfo {
name: String,
command: String,
user: String,
} }
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
@ -34,48 +45,42 @@ struct SystemStats {
#[tauri::command] #[tauri::command]
async fn get_processes(state: State<'_, AppState>) -> Result<(Vec<ProcessInfo>, SystemStats), String> { async fn get_processes(state: State<'_, AppState>) -> Result<(Vec<ProcessInfo>, SystemStats), String> {
let mut sys = state.sys.lock().map_err(|_| "Failed to lock system state")?; let mut sys = state.sys.lock().map_err(|_| "Failed to lock system state")?;
sys.refresh_processes(); let mut process_cache = state.process_cache.lock().map_err(|_| "Failed to lock process cache")?;
sys.refresh_memory();
sys.refresh_cpu(); // Batch refresh system information
sys.refresh_all();
let users_cache = UsersCache::new();
let processes = sys.processes() let processes = sys.processes()
.iter() .iter()
.map(|(pid, process)| { .map(|(pid, process)| {
let pid_u32 = pid.as_u32();
// Get or update cache for static process info
let static_info = process_cache.entry(pid_u32).or_insert_with(|| {
ProcessStaticInfo {
name: process.name().to_string(),
command: process.cmd().join(" "),
user: process.user_id()
.map_or_else(|| "-".to_string(), |uid| uid.to_string()),
}
});
let status = match process.status() { let status = match process.status() {
ProcessStatus::Run => "Running", ProcessStatus::Run => "Running",
ProcessStatus::Sleep => "Sleeping", ProcessStatus::Sleep => "Sleeping",
ProcessStatus::Idle => "Idle", ProcessStatus::Idle => "Idle",
ProcessStatus::Stop => "Stopped", _ => "Unknown"
ProcessStatus::Zombie => "Zombie",
ProcessStatus::Tracing => "Tracing",
ProcessStatus::Dead => "Dead",
ProcessStatus::Wakekill => "Wake Kill",
ProcessStatus::Waking => "Waking",
ProcessStatus::Parked => "Parked",
ProcessStatus::LockBlocked => "Lock Blocked",
ProcessStatus::UninterruptibleDiskSleep => "Disk Sleep",
ProcessStatus::Unknown(_) => "Unknown"
}; };
let user = process.user_id()
.and_then(|uid| {
let uid_num = uid.to_string().parse::<u32>().unwrap_or(0);
users_cache.get_user_by_uid(uid_num)
.map(|user| format!("{} ({})", user.name().to_string_lossy(), uid_num))
})
.unwrap_or_else(|| "-".to_string());
ProcessInfo { ProcessInfo {
pid: pid.as_u32(), pid: pid_u32,
ppid: process.parent().unwrap_or(sysinfo::Pid::from(0)).as_u32(), ppid: process.parent().unwrap_or(sysinfo::Pid::from(0)).as_u32(),
name: process.name().to_string(), name: static_info.name.clone(),
cpu_usage: process.cpu_usage(), cpu_usage: process.cpu_usage(),
memory_usage: process.memory(), memory_usage: process.memory(),
status: status.to_string(), status: status.to_string(),
user, user: static_info.user.clone(),
command: process.cmd().join(" "), command: static_info.command.clone(),
threads: None, threads: None,
} }
}) })
@ -107,6 +112,8 @@ fn main() {
tauri::Builder::default() tauri::Builder::default()
.manage(AppState { .manage(AppState {
sys: Mutex::new(System::new_all()), sys: Mutex::new(System::new_all()),
process_cache: Mutex::new(HashMap::new()),
last_update: Mutex::new(Instant::now()),
}) })
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
get_processes, get_processes,