[PR #228] feat: recognize the served model and the owning service in the COMMAND column #227

Open
opened 2026-10-02 23:15:09 -06:00 by gitea-mirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/XuehaiPan/nvitop/pull/228
Author: @xusy-sz
Created: 9/21/2026
Status: 🔄 Open

Base: main ← Head: feat/model-service-recognition


📝 Commits (2)

  • cfaebeb feat(api): recognize the served model and the owning service of processes
  • 1d4afac feat(tui): show the full command line and the working directory in the process details

📊 Changes

21 files changed (+1945 additions, -42 deletions)

View changed files

📝 CHANGELOG.md (+2 -0)
📝 README.md (+25 -6)
➕ docs/source/api/recognizer.rst (+40 -0)
📝 docs/source/index.rst (+1 -0)
📝 docs/source/spelling_wordlist.txt (+8 -0)
📝 nvitop/__init__.py (+2 -0)
📝 nvitop/api/__init__.py (+1 -0)
📝 nvitop/api/process.py (+12 -6)
➕ nvitop/api/recognizer.py (+597 -0)
📝 nvitop/cli.py (+22 -0)
📝 nvitop/tui/library/__init__.py (+10 -1)
📝 nvitop/tui/library/process.py (+13 -2)
📝 nvitop/tui/screens/metrics.py (+144 -27)
📝 pyproject.toml (+5 -0)
📝 setup.py (+3 -0)
➕ tests/conftest.py (+28 -0)
➕ tests/test_metrics_details.py (+175 -0)
➕ tests/test_recognizer.py (+358 -0)
➕ tests/test_recognizer_container.py (+178 -0)
➕ tests/test_recognizer_service.py (+62 -0)

...and 1 more files

📄 Description

Motivation

Inference engines rename their worker processes with setproctitle: vLLM shows VLLM::EngineCore, and ollama's embedded vLLM workers do the same. On a shared GPU server this makes the process table uninformative — several VLLM::EngineCore rows on one card, with no way to tell which model owns the memory without logging into the box and digging through /proc. A bare python main.py is equally anonymous.

This PR enriches the COMMAND column so the table answers "which model is this, whose service is this" at a glance.

What it does

  • Engine processes renamed to the ENGINE::role convention show the model looked up on the parent chain: --served-model-name / --model / --model-id / --model_name flags, the positional argument of serve, HuggingFace cache paths (models--Org--Name), and Ollama blob paths resolved through the manifests of the model store. Works for vLLM, SGLang, ollama's vLLM workers, and other engines following the convention.
  • Interpreter scripts show the owning project directory: main.py @ octopus-api.
  • Containerized processes (Docker, LXD) show the container name and the container view of the path: main.py @ vllm-svc:/workspace.
  • The process metrics screen (Enter) additionally shows the full command line (wrapped, wide-character aware) and the working directory.
  • Unrecognized processes keep their original command text byte-identically, and the whole feature can be turned off with --no-model-detect / NVITOP_NO_MODEL_DETECT=1.

Before / after, from a real fleet (ollama's vLLM workers, paddleocr genai_server --backend vllm in Docker, bare scripts):

Before After
before after

Design

  • Single seam: the TUI process class overrides command(); nvitop.api keeps the raw text, so library and exporter consumers are unaffected.
  • Pluggable rules: engine rules and service rules are registries; the first matching rule provides the label, and container attribution composes uniformly. New engines should need one small function.
  • Fallback contract: when nothing is recognized, the display is byte-identical to the current behavior (locked by tests, including the batch print path).
  • Performance: process facts (parent chain, cwd, cgroup) are gathered once per PID with TTL caches on the snapshot thread; Docker name lookups are cached per container ID; unreadable facts are cached with a shorter TTL so they are retried.
  • Scope: no new columns, no GPU-panel summary, no remote transport. Kubernetes pods and processes hidden by PID namespaces are deliberately out of scope.

Testing

  • This distribution ships no test infrastructure yet, so tests/ is new (pytest): 107 tests covering the recognizer boundary, the fallback contract, the switch, the platform guard, container cgroup fixtures (Docker cgroupfs/systemd, LXD, k8s ignored), and the detail view helpers. The layout helper is verified to fill the terminal height exactly.
  • ruff check / ruff format clean; mypy clean on the new module (no new errors project-wide).
  • Verified on a fleet of GPU servers against real workloads: vLLM under ollama, paddleocr genai_server --backend vllm inside Docker, LXD services, and bare python main.py scripts.

Notes

  • Happy to flip the default to opt-in if maintainers prefer the conservative default; the switch exists either way.
  • The metrics screen gains three header rows, so its minimum comfortable terminal height moves from 18 to 21 rows; below that the graph areas clamp as before and the terminal clips the bottom.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/XuehaiPan/nvitop/pull/228 **Author:** [@xusy-sz](https://github.com/xusy-sz) **Created:** 9/21/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/model-service-recognition` --- ### 📝 Commits (2) - [`cfaebeb`](https://github.com/XuehaiPan/nvitop/commit/cfaebeb8b2723e6c52dc7e09aa5c1e15e00b0e30) feat(api): recognize the served model and the owning service of processes - [`1d4afac`](https://github.com/XuehaiPan/nvitop/commit/1d4afac7934eea0825f469a64900b029bf99b6e3) feat(tui): show the full command line and the working directory in the process details ### 📊 Changes **21 files changed** (+1945 additions, -42 deletions) <details> <summary>View changed files</summary> 📝 `CHANGELOG.md` (+2 -0) 📝 `README.md` (+25 -6) ➕ `docs/source/api/recognizer.rst` (+40 -0) 📝 `docs/source/index.rst` (+1 -0) 📝 `docs/source/spelling_wordlist.txt` (+8 -0) 📝 `nvitop/__init__.py` (+2 -0) 📝 `nvitop/api/__init__.py` (+1 -0) 📝 `nvitop/api/process.py` (+12 -6) ➕ `nvitop/api/recognizer.py` (+597 -0) 📝 `nvitop/cli.py` (+22 -0) 📝 `nvitop/tui/library/__init__.py` (+10 -1) 📝 `nvitop/tui/library/process.py` (+13 -2) 📝 `nvitop/tui/screens/metrics.py` (+144 -27) 📝 `pyproject.toml` (+5 -0) 📝 `setup.py` (+3 -0) ➕ `tests/conftest.py` (+28 -0) ➕ `tests/test_metrics_details.py` (+175 -0) ➕ `tests/test_recognizer.py` (+358 -0) ➕ `tests/test_recognizer_container.py` (+178 -0) ➕ `tests/test_recognizer_service.py` (+62 -0) _...and 1 more files_ </details> ### 📄 Description ## Motivation Inference engines rename their worker processes with `setproctitle`: vLLM shows `VLLM::EngineCore`, and ollama's embedded vLLM workers do the same. On a shared GPU server this makes the process table uninformative — several `VLLM::EngineCore` rows on one card, with no way to tell which model owns the memory without logging into the box and digging through `/proc`. A bare `python main.py` is equally anonymous. This PR enriches the `COMMAND` column so the table answers "which model is this, whose service is this" at a glance. ## What it does - Engine processes renamed to the `ENGINE::role` convention show the model looked up on the parent chain: `--served-model-name` / `--model` / `--model-id` / `--model_name` flags, the positional argument of `serve`, HuggingFace cache paths (`models--Org--Name`), and Ollama blob paths resolved through the manifests of the model store. Works for vLLM, SGLang, ollama's vLLM workers, and other engines following the convention. - Interpreter scripts show the owning project directory: `main.py @ octopus-api`. - Containerized processes (Docker, LXD) show the container name and the container view of the path: `main.py @ vllm-svc:/workspace`. - The process metrics screen (<kbd>Enter</kbd>) additionally shows the full command line (wrapped, wide-character aware) and the working directory. - Unrecognized processes keep their original command text byte-identically, and the whole feature can be turned off with `--no-model-detect` / `NVITOP_NO_MODEL_DETECT=1`. Before / after, from a real fleet (ollama's vLLM workers, `paddleocr genai_server --backend vllm` in Docker, bare scripts): | Before | After | | --- | --- | | ![before](https://raw.githubusercontent.com/xusy-golden-tech/nvitop/pr-assets/before.png) | ![after](https://raw.githubusercontent.com/xusy-golden-tech/nvitop/pr-assets/after.png) | ## Design - **Single seam**: the TUI process class overrides `command()`; `nvitop.api` keeps the raw text, so library and exporter consumers are unaffected. - **Pluggable rules**: engine rules and service rules are registries; the first matching rule provides the label, and container attribution composes uniformly. New engines should need one small function. - **Fallback contract**: when nothing is recognized, the display is byte-identical to the current behavior (locked by tests, including the batch print path). - **Performance**: process facts (parent chain, cwd, cgroup) are gathered once per PID with TTL caches on the snapshot thread; Docker name lookups are cached per container ID; unreadable facts are cached with a shorter TTL so they are retried. - **Scope**: no new columns, no GPU-panel summary, no remote transport. Kubernetes pods and processes hidden by PID namespaces are deliberately out of scope. ## Testing - This distribution ships no test infrastructure yet, so `tests/` is new (pytest): 107 tests covering the recognizer boundary, the fallback contract, the switch, the platform guard, container cgroup fixtures (Docker cgroupfs/systemd, LXD, k8s ignored), and the detail view helpers. The layout helper is verified to fill the terminal height exactly. - `ruff check` / `ruff format` clean; `mypy` clean on the new module (no new errors project-wide). - Verified on a fleet of GPU servers against real workloads: vLLM under ollama, `paddleocr genai_server --backend vllm` inside Docker, LXD services, and bare `python main.py` scripts. ## Notes - Happy to flip the default to opt-in if maintainers prefer the conservative default; the switch exists either way. - The metrics screen gains three header rows, so its minimum comfortable terminal height moves from 18 to 21 rows; below that the graph areas clamp as before and the terminal clips the bottom. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
github-starred/nvitop#227
No description provided.