github.com/OrelSokolov/sysinfo.cr
1.1.0 / published Oct 31, 2026 / repository
Cross-platform system & process memory info for Crystal — a small port of the Rust sysinfo crate's surface: global RAM stats plus a pid/parent/RSS process table with process-tree RSS summation. Linux reads /proc, macOS uses libproc + Mach host_statistics64, Windows uses Toolhelp32 + GetProcessMemoryInfo.
sysinfo.cr
Cross-platform system & process memory info for Crystal — a small port of the Rust sysinfo crate's surface:
Sysinfo.memory— global RAM:total_kb/available_kb/used_kb/percentSysinfo.refresh_processes— rebuild the pid / parent / RSS snapshotSysinfo.processes— the last snapshot (Sysinfo::Processentries)Sysinfo.process_tree_memory_kb(pid)— RSS of a process and all its descendants (what a terminal tab actually uses: the shell plus its compilers/servers/agents), cycle-safeSysinfo.refresh_cpu/Sysinfo.cpu_percentages— per-core busy percent since the previous sample (first call is a baseline of zeros)Sysinfo.refresh_network/Sysinfo.network— bytes received/sent since boot plus average rates since the previous sample, loopback excludedSysinfo.refresh_gpus/Sysinfo.gpus— oneSysinfo::Gpuper card: load, VRAM used/total/percent, temperature, power and power limit (plus PCIe gen/width on NVIDIA). Unreadable values arenil; nothing here can raise into the caller.Sysinfo.refresh_sensors/Sysinfo.sensors— oneSysinfo::Sensorper temperature input (chip, label, current / max / critical °C). Unreadable values arenil; nothing here can raise into the caller.
The library is synchronous, like the Rust crate — callers decide when and where to refresh (h2term hides it on a background fiber).
Backends
| Platform | RAM | Process table | CPU cores | Network | GPU | Temp sensors |
|---|---|---|---|---|---|---|
| Linux | /proc/meminfo | /proc/<pid>/status (PPid + VmRSS) | /proc/stat | /proc/net/dev | NVML (dlopen) + amdgpu sysfs + Level Zero (dlopen) | hwmon sysfs |
| macOS | sysctl + host_statistics64 | libproc (proc_listallpids, proc_pidinfo) | host_processor_info | sysctl(NET_RT_IFLIST2) | — | — |
| Windows | GlobalMemoryStatusEx | Toolhelp32 + GetProcessMemoryInfo | NtQuerySystemInformation | GetIfTable2 | NVML (LoadLibraryA) + Level Zero (LoadLibraryA) | — |
| Other | nil | empty | — | — | — | — |
GPU readings come from the same sources Strata's monitor uses: NVIDIA's
own NVML library, loaded at runtime from the driver (libnvidia-ml.so.1
/ nvml.dll) so there is no compile-time binding, and — on Linux — the
amdgpu driver's sysfs files (KFD topology → renderD* device →
gpu_busy_percent, mem_info_vram_*, the hwmon temperature/power
sensors); no ROCm library needed. AMD on Windows would need ADL, so it
is not covered there.
Intel GPUs (integrated and Arc) go through Level Zero Sysman, Intel's
cross-platform GPU API (Linux libze_loader.so.1 from the
intel-level-zero-gpu package, Windows ze_loader.dll from the
graphics driver), runtime-loaded the same way as NVML. VRAM and
temperature are point-in-time reads — on iGPUs the memory module is the
shared-memory budget the driver exposes, not dedicated chips — while
engine load and power are monotonic counters, so they are computed
between two refresh_gpus calls (the first refresh reports nil).
On Linux /proc's top level lists only thread-group leaders, so
per-thread RSS can never be double-counted (upstream sysinfo has to
filter thread entries explicitly). On macOS, proc_pidinfo only
succeeds for processes the current uid may signal; the snapshot skips
everyone else.
Temperature sensors come from hwmon sysfs (/sys/class/hwmon) on
Linux — the same tree the sensors tool reads: one Sysinfo::Sensor
per temp<N>_input (CPU packages and cores, drive controllers, GPUs,
ACPI zones), with the chip name, the sensor label and the driver's
max/critical limits when it publishes them. Windows (WMI/SMBIOS) and
macOS (SMC) would each need their own plumbing and report no sensors
here.
Use
require "sysinfo"
if mem = Sysinfo.memory
puts "RAM #{mem.used_kb // 1024}/#{mem.total_kb // 1024} MB (#{mem.percent}%)"
end
Sysinfo.refresh_processes
Sysinfo.process_tree_memory_kb(Process.pid) # => whole tree RSS in KB
A live monitor example (per-core CPU load, RAM, network throughput,
GPU readings, temperature sensors) lives in example/monitor.cr:
crystal run example/monitor.cr
macOS note: on current kernels the interface byte counters come back with the high 32 bits zeroed, so totals wrap at 4 GB — the rate math uses wrapping deltas and stays correct across the wrap.
Test
crystal spec