Repository navigation
Home
A detailed breakdown of how memz collects kernel telemetry, computes regression metrics, and isolates background workloads from the terminal rendering loop.
- Architecture and Concurrency
- Kernel Data Acquisition
- Memory Math and Accounting
- Statistical Leak Detection
- Adaptive Polling Engine
- Data Pipeline and Table Projections
- Configuration Storage
- Performance Characteristics
memz separates raw data extraction from terminal rendering using an asynchronous worker model connected by bounded channels.
┌─────────────────────────────────────────────────────────────────┐
│ Terminal Layer (terminal/) │
│ │
│ tui.rs ───► 60 FPS Event Loop (Non-blocking crossterm poll) │
│ Keyboard and Mouse Event Router │
│ │
│ ui.rs ───► Ratatui Render Engine │
│ Stateless Frame Generator │
└────────────────────────────────┬────────────────────────────────┘
│ MPSC Channels
│ State Rx (sync_channel(1))
│ Inspect Rx (sync_channel(1))
│ Command Tx (channel())
┌────────────────────────────────┴────────────────────────────────┐
│ App Layer (app/) │
│ │
│ state.rs ──► Table Navigation, Sort and Group Projections │
│ Baseline Differential Computations │
│ │
│ config.rs ──► Session State and Theme Storage (XDG / AppData) │
│ │
│ engine.rs ──► Background Worker Controller │
└────────────────────────────────┬────────────────────────────────┘
│ Thread Handoff
│ Runtime Commands (Kill, Inspect, Mode)
│ String Caching with Arc<str>
┌────────────────────────────────┴────────────────────────────────┐
│ Core Layer (core/) │
│ │
│ collector.rs ──► Linux procfs Parser and sysinfo Backend │
│ Single-Pass smaps_rollup and NUMA Reader │
│ │
│ analyzer.rs ──► Linear Regression Engine │
│ PSI Pressure Evaluator and dt Normalization │
└─────────────────────────────────────────────────────────────────┘
-
Terminal Render Loop (Main Thread)
- Listens for terminal events using
crossterm::event::pollwith a 16ms timeout (targetting 60 FPS). - Only runs full layout redraws when new telemetry data arrives or when the user interacts with the keyboard or mouse.
- Never performs blocking file I/O or procfs reads directly on the main thread.
- Listens for terminal events using
-
Telemetry Engine (Worker Thread)
- Runs in a background OS thread spawned during initialization.
- Periodically walks procfs, computes NUMA usage, and executes leak detection math.
- Passes fresh
AnalyzedStateframes via a boundedsync_channel(1). If the main thread is busy drawing, older frames are dropped automatically to prevent stale telemetry buildup. - Listens for incoming commands (
Kill,Inspect,SetTickMode,Shutdown) on an unbounded control channel.
-
String Allocation Strategy
- Process names and command lines are wrapped in
Arc<str>. - Repeated sampling loops reuse the existing heap pointer for known processes, preventing thousands of tiny string allocations each second.
- Process names and command lines are wrapped in
memz gathers memory metrics through several standard Linux virtual files:
-
/proc/meminfo: Used for overall system metrics (such asMemTotal,MemFree,MemAvailable,Cached,Buffers,Slab,PageTables,SwapTotal, andSwapFree). -
/proc/[pid]/smaps_rollup: Provides aggregated memory counters for a process in roughly ten lines of text. Usingsmaps_rollupinstead of parsing thousands of lines in/proc/[pid]/smapsreduces file I/O overhead by two to three orders of magnitude. -
/proc/[pid]/smaps: Read only when you select a process and hitEnter. This extracts category details (heap, stack, anonymous memory, and dynamic libraries). -
/proc/pressure/memory: Kernel Pressure Stall Information (PSI). Evaluatesavg10numbers for bothsome(at least one process delayed by memory reclaim) andfull(all runnable threads stalled waiting for memory). -
/sys/devices/system/node/node[N]/meminfo: Gathers hardware NUMA node capacities and usage figures.
Resident Set Size (RSS) simply adds together all physical pages mapped into a process:
When glibc), standard RSS counts that library
Proportional Set Size (PSS) corrects for this by dividing shared pages among all processes holding an active reference:
Linux does not provide a single counter for total kernel memory allocations. memz estimates kernel space by subtracting accounted user and system structures from total RAM:
This residual approximation covers in-kernel structures, DMA buffers, network socket queues, and device driver allocations.
Instead of watching for small step increases that could just be regular heap fragmentation, memz evaluates the slope of a rolling sample history (
Given sample points
The growth slope (
Because the sampling rate can speed up or slow down based on system activity, the raw sample slope is normalized against the actual elapsed time (
A process is marked with a red [LEAK?] tag only when all four checks pass:
- At least 8 continuous samples are on record.
- The normalized growth rate is at least
$32\text{ KB/s}$ . - Linear correlation
$R^2$ is$0.70$ or higher. - Temporary downward dips do not exceed one third of the overall growth span.
memz automatically adjusts how often it queries the kernel based on memory pressure:
| Mode | Polling Interval | Why It Switches |
|---|---|---|
| Eco | Normal conditions, no thrashing, healthy PSI indicators, and no leaks. | |
| Normal | User has a process inspector popup open. | |
| Fast | Memory thrashing ( |
You can use + or - to manually lock the engine into Fast, Normal, or Eco speeds, or return it to Auto.
Data travels through a multi-stage pipeline before reaching the screen:
Kernel procfs / sysinfo
│
▼
AnalyzedState (ProcessStats[])
│
├─► Substring Search (matching name or PID)
│
├─► Process Grouping (combining matching binary names)
│
├─► Snapshot Differentials (relative to saved baseline)
│
▼
DisplayRow[] (Projected Table Model)
│
▼
Ratatui Table Rendering (viewport offset and selection)
When grouping (g) is switched on:
- All processes sharing the same binary name are grouped into a single row.
- PSS, RSS, Shared, Private, and Swap counters are added together.
- Individual history buffers are merged chronologically to allow leak detection across the entire group.
- The PID column shows the count of running instances (for example,
12x).
Preferences are loaded at startup and saved upon exit using a simple key-value file without pulling in heavy serialization crates:
-
Linux and macOS:
$XDG_CONFIG_HOME/memz/state.conf(falls back to~/.config/memz/state.conf). -
Windows:
%APPDATA%\memz\state.conf(falls back to%USERPROFILE%\.config\memz\state.conf).
Stored format:
theme=ember_orange
view_mode=processes
sort_mode=pss
tick_mode=auto
grouped=false-
CPU Utilization: Stays under
$0.8%$ of a single core on modern systems at 1-second polling intervals with 500 active processes. -
Resident Memory: Takes up between
$4.5\text{ MiB}$ and$8.5\text{ MiB}$ of RAM. -
Kernel I/O Speed: Sequential reads of
/proc/[pid]/smaps_rollupgenerally finish within$15\text{ to }30\text{ ms}$ per cycle. -
Terminal Rendering: Uses Ratatui double-buffering to write only changed screen cells, completing frame draws in less than
$2\text{ ms}$ .