sysinfo | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / sysinfo

sysinfo

maintained by johnlindquist

star 19 account_tree 3 verified_user MIT License
bolt View GitHub

name: sysinfo description: System and process information for Rust applications version: "0.33"

sysinfo

Cross-platform library for retrieving system information: processes, CPUs, memory, disks, and networks.

Key Types

Core Types

Type Purpose
System Main struct holding all system information
Process Information about a single process
Pid Process identifier (platform-specific wrapper)
ProcessesToUpdate Enum specifying which processes to refresh

Refresh Kind Types (Performance Critical)

Type Purpose
ProcessRefreshKind Controls what process info to refresh
RefreshKind Controls what system info to refresh
UpdateKind Never, OnlyIfNotSet, or Always

Usage in script-kit-gpui

Process Manager (process_manager.rs)

The crate is used for orphan process detection - checking if child bun processes are still running:

use sysinfo::{Pid, System};

/// Check if a process is currently running
pub fn is_process_running(&self, pid: u32) -> bool {
    let mut system = System::new();
    system.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
    system.process(Pid::from_u32(pid)).is_some()
}

Key patterns used:

  • System::new() - Create minimal system instance
  • refresh_processes(ProcessesToUpdate::All, true) - Refresh all processes, remove dead ones
  • system.process(Pid::from_u32(pid)) - Look up specific process by PID
  • Pid::from_u32() - Convert platform u32 to sysinfo's Pid type

Process Information

Checking if Process Exists

use sysinfo::{Pid, ProcessesToUpdate, System};

let mut sys = System::new();
sys.refresh_processes(ProcessesToUpdate::All, true);

// Check by PID
if let Some(process) = sys.process(Pid::from_u32(1234)) {
    println!("Process {} is running", process.name().to_string_lossy());
}

// Check specific PIDs only (more efficient)
let pids = [Pid::from_u32(1234), Pid::from_u32(5678)];
sys.refresh_processes(ProcessesToUpdate::Some(&pids), true);

Process Properties

// Available on Process
process.pid()           // -> Pid
process.name()          // -> &OsStr (limited to 15 chars on Linux!)
process.exe()           // -> Option<&Path>
process.cmd()           // -> &[OsString]
process.cwd()           // -> Option<&Path>
process.environ()       // -> &[OsString]
process.memory()        // -> u64 (RSS in bytes)
process.virtual_memory() // -> u64
process.cpu_usage()     // -> f32 (percentage)
process.status()        // -> ProcessStatus
process.parent()        // -> Option<Pid>
process.start_time()    // -> u64 (Unix timestamp)
process.run_time()      // -> u64 (seconds)

Killing Processes

use sysinfo::Signal;

// Simple kill (SIGKILL)
process.kill();

// Kill with specific signal
if let Some(success) = process.kill_with(Signal::Term) {
    println!("Signal sent: {}", success);
}

// Wait for termination
process.wait();

Refresh Patterns

CRITICAL: Always Refresh Before Reading

sysinfo works on diffs - you must refresh to get current data:

// BAD - stale data
let sys = System::new_all();
let mem = sys.used_memory(); // May be outdated!

// GOOD - fresh data  
let mut sys = System::new();
sys.refresh_memory();
let mem = sys.used_memory();

Performance: Refresh Only What You Need

use sysinfo::{ProcessRefreshKind, ProcessesToUpdate, System};

// SLOW - refreshes everything
sys.refresh_all();

// FAST - only refresh processes, only memory info
sys.refresh_processes_specifics(
    ProcessesToUpdate::All,
    true, // remove dead processes
    ProcessRefreshKind::nothing().with_memory(),
);

// FASTEST - check specific PIDs only
let pids = [Pid::from_u32(1234)];
sys.refresh_processes(ProcessesToUpdate::Some(&pids), true);

ProcessRefreshKind Builder

use sysinfo::{ProcessRefreshKind, UpdateKind};

// Nothing (fastest)
ProcessRefreshKind::nothing()

// Everything (slowest)
ProcessRefreshKind::everything()

// Custom - only what you need
ProcessRefreshKind::nothing()
    .with_memory()      // RSS, virtual memory
    .with_cpu()         // CPU usage
    .with_disk_usage()  // Disk I/O
    .with_exe(UpdateKind::OnlyIfNotSet) // Executable path

Reuse System Instance

// BAD - creates new instance each time
fn check_process(pid: u32) -> bool {
    let mut sys = System::new();
    sys.refresh_processes(ProcessesToUpdate::All, true);
    sys.process(Pid::from_u32(pid)).is_some()
}

// GOOD - reuse instance (especially for CPU usage which needs history)
struct ProcessMonitor {
    sys: System,
}

impl ProcessMonitor {
    fn check_process(&mut self, pid: u32) -> bool {
        self.sys.refresh_processes(ProcessesToUpdate::All, true);
        self.sys.process(Pid::from_u32(pid)).is_some()
    }
}

CPU Usage Notes

CPU usage requires two measurements with time between them:

use sysinfo::{System, MINIMUM_CPU_UPDATE_INTERVAL};
use std::thread;

let mut sys = System::new_all();

// First measurement (will be 0%)
sys.refresh_cpu_usage();

// Wait minimum interval
thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);

// Second measurement (accurate)
sys.refresh_cpu_usage();

for cpu in sys.cpus() {
    println!("{}%", cpu.cpu_usage());
}

Platform Differences

Process Names on Linux

  • Limited to 15 characters
  • May not match executable name
  • Use process.exe() for full path when available

macOS Sandboxing

For App Store apps, use feature flags:

[dependencies]
sysinfo = { version = "0.33", features = ["apple-app-store"] }

Windows

  • Admin privileges may be needed for some process info
  • PID is usize, not pid_t

Pid Conversions

use sysinfo::Pid;

// From u32 (most portable)
let pid = Pid::from_u32(1234);

// To u32
let n: u32 = pid.as_u32();

// From/to usize (platform-specific)
let pid = Pid::from(1234_usize);
let n: usize = pid.into();

// Parse from string
let pid: Pid = "1234".parse().unwrap();

Anti-patterns

Creating System::new_all() Repeatedly

// BAD - expensive allocation every call
fn get_memory() -> u64 {
    System::new_all().used_memory()
}

// GOOD - reuse instance
fn get_memory(sys: &mut System) -> u64 {
    sys.refresh_memory();
    sys.used_memory()
}

Not Refreshing Before Reading

// BAD - returns initialization values (often 0)
let sys = System::new();
let procs = sys.processes(); // Empty!

// GOOD
let mut sys = System::new();
sys.refresh_processes(ProcessesToUpdate::All, true);
let procs = sys.processes();

Refreshing Everything When You Need One Thing

// BAD - refreshes CPUs, memory, processes, etc.
sys.refresh_all();
let mem = sys.used_memory();

// GOOD - only refresh memory
sys.refresh_memory();
let mem = sys.used_memory();

Trusting process.name() on Linux

// BAD - may be truncated or changed
let name = process.name(); // "my-very-long-a" (truncated!)

// GOOD - use exe when available
let name = process.exe()
    .and_then(|p| p.file_name())
    .map(|n| n.to_string_lossy().to_string())
    .unwrap_or_else(|| process.name().to_string_lossy().to_string());

Reading CPU Usage Without History

// BAD - first reading is always 0%
let mut sys = System::new_all();
let cpu = sys.global_cpu_usage(); // 0%!

// GOOD - wait for second sample
let mut sys = System::new_all();
std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
sys.refresh_cpu_usage();
let cpu = sys.global_cpu_usage(); // Accurate!

Common Patterns

Find Process by Name

// Exact name match
for process in sys.processes_by_exact_name("bun".as_ref()) {
    println!("{}: {}", process.pid(), process.name().to_string_lossy());
}

// Substring match  
for process in sys.processes_by_name("bun".as_ref()) {
    println!("{}: {}", process.pid(), process.name().to_string_lossy());
}

Monitor Process Until Exit

use std::time::Duration;

fn wait_for_exit(pid: u32, timeout: Duration) -> bool {
    let mut sys = System::new();
    let deadline = std::time::Instant::now() + timeout;
    let target_pid = Pid::from_u32(pid);
    
    while std::time::Instant::now() < deadline {
        sys.refresh_processes(
            ProcessesToUpdate::Some(&[target_pid]),
            true
        );
        if sys.process(target_pid).is_none() {
            return true; // Process exited
        }
        std::thread::sleep(Duration::from_millis(100));
    }
    false // Timeout
}

Feature Flags

[dependencies]
sysinfo = { version = "0.33", default-features = false }

# Optional features:
# - multithread: Parallel refresh (increases memory on macOS)
# - serde: Serialize System and related types
# - apple-app-store: Disable APIs prohibited in App Store
# - apple-sandbox: Sandbox-safe subset

References

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 19
GitHub Forks 3
Created Jan 2026
Last Updated 5 months ago
tools tools debugging

Related Skills

fabric
chevron_right
typescript-expert
chevron_right
break-loop
chevron_right
burp-suite
chevron_right
page-behavior-audit
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.