# performance_monitor **Repository Path**: pikailo/performance_monitor ## Basic Information - **Project Name**: performance_monitor - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-14 - **Last Updated**: 2026-07-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PerfMonitor 跨平台实时系统性能监控工具,提供 Web 界面。可选择运行中的进程,实时查看其 **CPU、内存、磁盘 I/O、网络速率、GPU(利用率 / 显存)** 曲线;进程网络在 Windows 使用 ETW、Ubuntu 使用 nethogs/libpcap、macOS 使用 nettop。并支持 **Booster 虚拟机器人 Docker 容器** 的 **仿真速度(实时因子,两位小数,可超过 1.00)** 独立监控。数据持久化到 SQLite,支持历史回放、导出与 `.log` 导入分析。 当前界面版本:**v1.3.1** 快速上手见项目根目录 **[readme.txt](readme.txt)**(简明步骤);本文档为完整说明。 ## 功能特性 ### 实时监控 - 可配置采样间隔(默认 1 秒),通过 **SSE** 推送至浏览器 - **CPU** 占用率(占整机逻辑 CPU 总容量,**每行 0~100%**)、**内存 RSS**、**进程 I/O 读/写速率**、**网络收/发速率**(Windows ETW、Ubuntu nethogs、macOS nettop,按 PID 聚合 **TCP+UDP**)、**GPU % / Dedicated VRAM**(按进程,启动时自动探测后端) - 实时默认 **一行五列**:CPU | 内存 | 磁盘 | 网络 | GPU;GPU 图可在 **利用率 / 显存** 间切换(单曲线) - 全部选中 PID 首次采到 **CPU + 内存** 后,再开始计时、写库与推流(界面显示「启动中 x/y」);磁盘/网络速率可稍后补点,无 `io_counters` 或无权限的进程磁盘显示「-」,不填假 0 - 锁屏/休眠/采样间隔异常时自动重立差分基准,避免假 0 与误导性斜线 - 实时曲线最多保留约 **1 小时** 窗口数据;Y 轴按数据自适应(单进程 CPU 约 0~100%;合并时轴可高于 100%) - 图表支持 **行/列布局**、时间轴缩放(拖拽选区)、多图同步十字线 - 停止监控后 / 历史回放:曲线上标 **峰值、最低**;图顶条带按线显示 **均值、中位数**(内存 RSS/专用、磁盘读/写、GPU 利用率/显存各一行;CPU 单行) ### 仿真速度(Booster 虚拟机器人) - **独立开关**:工具栏「监控仿真速度」,与进程「开始/停止监控」解耦,可单独或同时开启 - 自动发现本机 Docker 容器名匹配 `*-k1`、`*-t1`、`*-t2`(如 `cvz4x-k1`),通过 `docker port 8788/tcp` 连接 Physics WebSocket - 默认 **1 Hz** 采样 `actual_speed_factor`,以 **两位小数实时因子** 显示(1.00 ≈ 实时,可超过 1.00;暂停时为 0.00) - 每个容器一张 **仿真速度** 折线图,样式与 CPU 曲线一致(缩放、十字线、停止后峰值/均值条带) - SSE 事件 **`sim_tick`** 推送;数据写入 SQLite 表 `sim_sessions` / `sim_speed_metrics`;支持**实时导出**(`GET /api/sim/export`)与**历史标签回放** - 需本机已安装 **Docker** 且 Booster 虚拟机器人容器在运行;依赖 `websockets`、`msgpack` 验证脚本(容器在跑时): ```bash python scripts/verify_sim_speed.py ``` 真实进程 CPU / 内存 / 磁盘采集与 SQLite 一致性验收: ```bash python scripts/verify_collector_accuracy.py ``` Ubuntu/macOS 真实 TCP 流量按 PID 归属验收: ```bash python scripts/verify_platform_network.py ``` ### 进程列表 - 搜索(支持 `;` 分隔多关键词)、按 PID/名称/CPU/内存排序 - **CPU %** 与实时监控、任务管理器「进程」列一致:`psutil` 原始值按逻辑核数归一后 **0~100%** - 多选、全选当前列表;已选数量与重名进程摘要(如 `已选 15,chrome(6),node(3)`) - 列表通过 **SSE `list_tick`** 刷新,节奏对齐 **任务管理器(约 1 Hz)**:**CPU / 内存 / 磁盘 / 网络** 约 **1 秒**;**GPU %** 独立线程约 **1 秒**(读 PDH 缓存,与 CPU enrich 解耦) - **网络列(收/发)**:Windows 使用 **ETW Kernel NETWORK_TCPIP** 的 1 秒事件时间窗;Ubuntu 使用 **nethogs trace/libpcap**;macOS 使用系统 **nettop** 累计字节。均按 PID 聚合 **TCP+UDP**,不是主机网卡总量。网络单位使用十进制 `kB/s`、`MB/s`、`GB/s`;悬停显示原始 `B/s`、十进制 `Mbps`、样本年龄与统计窗。Windows 还拆分显式回环流量,并显示自 PID 身份基线后的累计字节;若 ETW 报告事件或实时缓冲区丢失,受影响窗口返回空值并自动重建累计基线,状态接口同时暴露丢失计数。依赖缺失、权限不足或后端未就绪时显示「-」,**绝不沿用旧速率或填假 0** - 列表预览按平台设置 watch 上限:Windows 最多 **500 PID**,Ubuntu/macOS 最多 **200 PID**;超过时固定保留已选、已展开分组和当前页中的高优先级 PID,不伪造未采样进程的实时值 - **实时监控进行中**:`watch` 置空,列表指标由 **`monitor_tick`(默认 1s)** 与曲线同步,不再走 `list_tick` - watch 集合变更时 **debounce PDH 全量重建**(默认 ≥8s),减轻 `list:tick_cpu` 被拖慢 - 按内存/专用工作集排序时,排行 API 使用短 TTL(约 1.5s)的机器级内存快照,减轻重复全量采样 ### 合并展示与选型策略 | 场景 | 行为 | |------|------| | 已选 ≤ 15 个不同进程名 | 自由勾选「合并同名」「汇总全部」或不合并 | | 已选 > 15 个不同进程名 | 须二选一:「合并同名」或「汇总全部」 | | 已选 > 50 个 PID | 强制「汇总全部」并锁定合并选项 | | 已选 > 平台上限 | 可继续勾选,但 **「开始监控」禁用**;Windows 上限 200 PID,Ubuntu/macOS 上限 100 PID,后端会再次强制校验且不会静默截断 | - **合并同名**:同名进程 CPU/内存/磁盘按时间戳聚合 - **汇总全部**:所有选中 PID 汇总为一组曲线 - 监控运行中或 **停止后** 均可切换合并方式(基于内存中的 PID 日志回放,带加载遮罩,避免图表闪烁) 前端默认值位于 `static/js/ui_limits.js`;实际平台上限由后端 `/api/config` 下发并由 `/api/monitor/start` 强制校验。 ### 历史会话 - 从 SQLite 加载历史会话列表,点击回放 CPU/内存/磁盘/GPU 曲线 - 支持「合并同名 / 汇总全部」切换(指标缓存,无需重复请求) - **分档加载(精度优先)**:≤12h 且行数适中可一次 bulk 全量;12h~48h 默认最近 6h 原始点;>48h(含 7×24h)默认最近 2h + 分块拉取;缩放时间轴时按窗补载 raw - 可配置外部历史库路径、删除单条/全部会话 - **导出** 会话或实时数据为 `.log`;**导入** `.log` 离线查看 - 压测库:`python scripts/seed_history_db.py --hours 168 --pids 20` ### 其他 - 深色 Web UI(macOS 风格),Chart.js v4 内置,无需 CDN - 推荐 **waitress** 作为生产 WSGI 服务器;未安装时回退 Flask 开发服务器 - 基于 **psutil**,支持 Windows、Linux、macOS ## 环境要求 - Python **3.10+** - 依赖见 `requirements.txt`: ``` psutil>=5.8.0 Flask>=3.0.0 waitress>=3.0.0 websockets>=12.0 # Booster 虚拟机器人仿真速度 WebSocket msgpack>=1.0.0 # physics simulation_state 解析 pywin32>=306; platform_system == "Windows" # PDH 进程 GPU(推荐,替代 PowerShell) nvidia-ml-py>=12.0.0 # NVIDIA 按进程 GPU(可选) darwin-perf>=1.1.0 # macOS Apple Silicon 按进程 GPU(可选) pyamdgpuinfo>=2.1.0 # Linux AMD 按进程 GPU(可选) ``` GPU 后端在 `monitor/platform_gpu.py` 启动时自动探测: - **Windows**:`win_perf`(进程内 **PDH** 采样 `GPU Engine`,需 `pywin32`;与任务管理器同源;**Intel / AMD / NVIDIA 均可用**) - **GPU % 说明**:低负载时 PDH 可能长期为 **0%**,任务管理器仍可能显示约 **1%**(平滑/归因不同);无 `GPU Engine` 计数器的子进程在列表中显示 **`-`**(`gpu_util_tracked=false`) - **macOS**:`darwin-perf`(Apple Silicon per-PID) - **NVIDIA 独显**:`nvml`(`nvidia-ml-py`,需安装 NVIDIA 驱动) 未探测到任何后端时不影响 CPU/内存监控。Windows 上若曾安装过 `nvidia-ml-py` 但无 NVIDIA 显卡,会忽略 NVML 并走 `win_perf`。 Chart.js v4 已内置在 `static/js/chart.umd.min.js`,无需 npm。 ### Linux(Debian / Ubuntu) 系统自带的 Python 受 [PEP 668](https://peps.python.org/pep-0668/) 保护,**不要**对全局环境执行 `pip3 install`(会报 `externally-managed-environment`)。请使用项目内虚拟环境: - 首次需安装 venv 组件(版本号与系统 Python 一致,例如 3.12): ```bash sudo apt install python3.12-venv python3-full # 可选:与 gnome-system-monitor 同源读内存(推荐) sudo apt install gir1.2-gtop-2.0 python3-gi ``` - 若执行 `python3 -m venv` 时报 `ensurepip is not available`,说明尚未安装上述包。 - 未安装 `gir1.2-gtop-2.0` 时,Linux 内存回退为读取 `/proc//statm`(算法与 libgtop 相同);进程列表约 **1 秒** 刷新内存,显示 **1 位小数** MiB。 - 实时监控时,进程表 **内存/常驻** 随 SSE 与采集间隔同步更新(与系统监视器刷新节奏接近)。 ## 快速开始 ```bash # 克隆仓库 git clone git@gitee.com:software_test_team/performance_monitor.git cd performance_monitor ``` ### Windows / macOS ```bash # 安装依赖(建议在虚拟环境中执行,见下方 Linux 步骤) pip install -r requirements.txt # 启动(默认 http://localhost:5000,并尝试打开浏览器) python main.py ``` ### Linux ```bash # 1. 创建并激活虚拟环境(目录 .venv 已在 .gitignore 中忽略) python3 -m venv .venv source .venv/bin/activate # 2. 在虚拟环境中安装依赖 pip install -r requirements.txt # 3. 精确进程网络(TCP+UDP) sudo apt install nethogs # 允许普通用户抓包;若系统策略不允许 capabilities,请用 sudo 启动 sudo setcap cap_net_admin,cap_net_raw+eip "$(command -v nethogs)" # 4. 启动 python main.py ``` 每次新开终端重新进入项目目录后,需先执行 `source .venv/bin/activate` 再运行 `python main.py`。提示符出现 `(.venv)` 表示已激活。 退出虚拟环境:`deactivate`。 ### 命令行参数 | 参数 | 默认值 | 说明 | |------|--------|------| | `--port PORT` | 5000 | HTTP 服务端口 | | `--host HOST` | `127.0.0.1` | 监听地址;仅在需要远程访问时显式使用 `0.0.0.0` | | `--interval SECONDS` | 1.0 | 采样间隔(秒) | | `--log-dir DIR` | `logs` | SQLite 数据库目录 | | `--retention-days N` | 0 | 启动时删除 N 天前已正常结束的历史会话;0 表示不自动删除 | | `--no-browser` | — | 启动时不自动打开浏览器 | | `--debug` | — | 开启性能诊断日志(stderr,约每 2 秒汇总) | ```bash python main.py --host 127.0.0.1 --port 8080 --interval 2 --log-dir ./data --no-browser ``` ### 性能诊断(监控 + 图表 + 列表) 用于定位卡顿在 **后端采样**、**SSE** 还是 **前端 DOM/Chart.js**。 **后端**(终端 stderr,每约 2 秒一行 `perf summary`): ```bash # PowerShell $env:PERF_MONITOR_LOG="1" python main.py # 或 python main.py --debug ``` 主要阶段:`list:tick_cpu` / `list:tick_gpu`(未监控列表)、`monitor:loop`(采集+写库+推流)、`monitor:sse_payload`(包大小)。单次超过约 80ms 会额外打 `perf slow`。 **前端**(浏览器控制台,每约 2 秒 `[PerfMonitor][perf] summary`;每 10 秒 `state` 快照): ```javascript localStorage.setItem('perfMonitorPerf', '1'); // 或 perfMonitorDebug=1 location.reload(); ``` 主要阶段:`sse:dispatch:*`、`list:apply_batch` / `list:cells` / `list:render`、`monitor:tick` / `monitor:chart_pid`、`chart:raf`。可配合 DevTools **Performance** 录屏对照 Long Task。 关闭前端:`localStorage.removeItem('perfMonitorPerf');` 后刷新。 **任务管理器验收**(`--debug` 或 `PERF_MONITOR_LOG=1`)stderr 关键字: | 日志 | 含义 | |------|------| | `tm cpu_ok` | 整表 enrich 耗时(2s 全量模式) | | `tm cpu_shard_slow` | 超大 watch 分片 enrich 超过目标耗时(当前默认平台上限通常不会触发) | | `tm tick_overrun` | 单轮 CPU tick 超过 1.15× 配置采样间隔 | | `tm tick_slow` / `perf slow list:tick_cpu` | enrich 仍过慢 | | `tm pdh_full_skipped` | PDH 全量重建已 debounce(正常) | | `tm watch_unchanged` | 重复 POST watch 已跳过 | 验收目标:默认约 **每 1s 更新整份已接收 watch**;Windows ≤500 PID、Ubuntu/macOS ≤200 PID。页面必须显示实际接收数,未进入 watch 的 PID 不得沿用旧值冒充实时数据。 ## 使用说明 ### 实时监控 1. 浏览器打开 `http://localhost:5000` 2. 在 **进程列表** 中搜索、排序并勾选目标进程 3. 按需勾选 **合并同名** 或 **汇总全部**(大量进程时界面会提示合并策略) 4. 点击 **开始监控** — 待全部 PID 指标就绪后,计时器开始走字,曲线开始更新 5. 使用缩放按钮或拖拽图表时间区域调整视窗;可关闭单张图表或通过「+」补回 CPU/内存/磁盘 6. 点击 **停止监控** 结束会话,数据写入 SQLite;可继续切换合并方式查看已采集曲线 7. **导出** 可将当前实时缓冲导出为 `.log` ### 仿真速度监控 1. 确保 Booster 虚拟机器人 Docker 容器已运行(`docker ps` 可见 `xxxx-k1` 等) 2. 打开页面后点击 **刷新**,确认工具栏显示容器名 3. 勾选 **监控仿真速度** — 约 1 秒后开始更新曲线;取消勾选即停止并显示峰值/均值 4. 可与进程实时监控同时使用,互不影响 ### 历史会话 1. 页面下方 **历史会话** 区域点击 **加载历史** 2. 点击某条会话 chip 回放;可用合并选项切换视图 3. **配置** 可指定其他 SQLite 路径(存于浏览器 `localStorage`) 4. **导入** `.log`、**导出** 选中会话、**清空历史** 删除库中记录 ## 项目结构 ``` main.py 命令行入口(waitress / Flask) config.py PerfConfig 默认配置 monitor/ collector.py 后台采样(MetricsCollector) sim_speed.py Booster 仿真速度采集(Docker 发现 + WebSocket) data_buffer.py 内存缓冲 + SQLite 批量写入 process_manager.py 进程枚举、搜索、信息补全 scripts/ verify_sim_speed.py 仿真速度 API 联调脚本 read_sim_speed.py 单次读取 simulation_state(调试用) web/ app.py Flask 路由与 REST API sse.py SSE 广播 static/ index.html 单页应用 css/style.css 深色主题 js/ app.js 监控生命周期、合并策略、SSE charts.js 实时 Chart.js、缩放、重建 history_store.js 历史分档拉数 / IndexedDB 缓存 history_data_worker.js 历史指标按 PID 分区(Worker) history.js 历史回放与导入 process_list.js 进程表与选型 UI sim_speed.js 仿真速度独立开关与 SSE ui_limits.js 监控/合并阈值(前端统一配置) chart.umd.min.js Chart.js v4 logs/ perf_monitor.db 默认数据库(首次运行后生成) ``` ## 数据流 ``` 用户勾选 PID → POST /api/monitor/start → MetricsCollector 守护线程按间隔 psutil 采样 → 全部 PID 首次 CPU+内存 样本 → 对齐 session 起点、metrics_ready=true → DataBuffer(内存)+ DataLogger(SQLite 批量写) → SSE /stream 推送到浏览器 → ChartManager 追加/合并曲线(切换合并时从 _pidLog 回放) 停止 → POST /api/monitor/stop → 刷写 DB、关闭会话 ``` 仿真速度(独立): ``` 勾选监控 → POST /api/sim/start → SimSpeedCollector 连接 ws://127.0.0.1: → 订阅 subscribe:simulation_state,解析 actual_speed_factor → 1 Hz 写入 SimSpeedBuffer + sim_speed_metrics → SSE sim_tick → ChartManager chartType=sim 取消 → POST /api/sim/stop → 关闭 sim_sessions ``` ## API 参考 | 方法 | 路由 | 说明 | |------|------|------| | GET | `/` | Web 前端 | | GET | `/api/processes` | 进程列表(`sort` `asc` `search`) | | POST | `/api/processes/enrich` | 批量补全 PID 的 CPU/内存 | | GET | `/api/processes/` | 单进程详情 | | POST | `/api/monitor/start` | 开始监控,body: `{"pids": [...]}` | | POST | `/api/monitor/stop` | 停止监控 | | GET | `/api/monitor/status` | `running` `metrics_ready` `elapsed` `active_pids` 等 | | GET | `/api/data/` | 内存缓冲中的指标序列 | | GET | `/api/config` | 当前库路径、采样间隔、`sim_speed_interval` | | GET | `/api/sim/targets` | 发现 `*-k1/t1/t2` 容器及 physics WebSocket 地址 | | POST | `/api/sim/start` | 开始仿真速度监控,body: `{"targets": ["cvz4x-k1"]}`(可省略则监控全部已发现容器) | | POST | `/api/sim/stop` | 停止仿真速度监控 | | GET | `/api/sim/status` | `running` `elapsed` `active_targets` `data_points` | | GET | `/api/sim/data/` | 内存缓冲中的仿真速度序列 | | GET | `/api/sim/export` | 导出当前仿真速度内存缓冲为 `sim_*.log` | | GET | `/api/sim/sessions` | 仿真速度历史会话列表 | | GET | `/api/sim/sessions//metrics` | 某 sim 会话指标(含 `metrics_by_target`) | | GET | `/api/sim/sessions//export` | 导出 sim 历史会话为 `.log` | | DELETE | `/api/sim/sessions/` | 删除 sim 历史会话 | | GET | `/api/sessions` | 历史会话列表(可选 `?db=` 自定义库) | | DELETE | `/api/sessions` | 删除全部会话(可选 `?db=`) | | DELETE | `/api/sessions/` | 删除单条会话 | | GET | `/api/sessions//metrics/meta` | 会话档位、行数、是否允许 bulk、首屏时间窗 | | GET | `/api/sessions//metrics` | 指标:无参 bulk(仅 S 档小会话);`from`/`to`/`after`/`limit`/`pids` 分窗与分块 | | GET | `/api/sessions//metrics?pid=` | 单 PID 全量(兼容) | | GET | `/api/sessions//export` | 导出会话为 `.log` | | GET | `/api/data/export` | 导出当前实时缓冲 | | POST | `/api/import` | 上传 `.log` 解析 | | GET | `/stream` | SSE 实时指标流(`list_tick` `monitor_tick` `sim_tick` 等) | ## SQLite 结构 默认路径:`logs/perf_monitor.db`(`--log-dir` 可改)。 | 表 | 主要字段 | |----|----------| | `sessions` | `id`, `start_time`, `end_time`, `monitor_interval`, … | | `monitored_processes` | `session_id`, `pid`, `process_name`, `username`, `executable_path` | | `metrics` | `session_id`, `pid`, `timestamp`, `cpu_percent`, `memory_rss`, `memory_vms`, `memory_percent`, `disk_read_bps`, `disk_write_bps` | | `sim_sessions` | `id`, `start_time`, `end_time`, `monitor_interval`, `metric_count` | | `sim_targets` | `session_id`, `target_name` | | `sim_speed_metrics` | `session_id`, `target`, `timestamp`, `speed_factor`, `paused`, `model_path` | 索引:`(session_id, pid)`、`(timestamp)`、`(session_id, pid, timestamp)`;仿真表 `(session_id, target)`。 ### 历史回放档位 | 档位 | 时长 | 默认加载 | 精度 | |------|------|----------|------| | S | ≤12h | 允许时一次 bulk 全会话 raw | DB 原始行 | | M | 12h~48h | 最近 6h raw,缩放补载 | 当前窗内 raw | | L | >48h | 最近 2h raw + chunk;不合并时最多绘 12 个 PID | 当前窗内 raw | 阈值见 `/api/config` 中 `history_*` 字段;大会话无参 `GET .../metrics` 返回 `400 use_range`。 ## 配置 `config.py` 中的 `PerfConfig`(部分可由命令行覆盖): | 字段 | 默认 | 说明 | |------|------|------| | `default_interval` | 1.0 | 采集器初始间隔(秒);CLI `--interval` 可改 | | `monitor_interval` | 1.0 | **实时监控**固定采集/SSE 间隔(秒);与 `list_tick` 独立 | | `max_data_points` | 1800 | 每 PID 内存缓冲上限(约 30 分钟 @1s) | | `db_batch_size` | 50 | SQLite 批量写入行数 | | `db_flush_interval` | 10.0 | 最大刷盘间隔(秒) | | `default_port` | 5000 | HTTP 端口 | | `log_dir` | `logs` | 数据目录 | | `sim_speed_interval` | 1.0 | 仿真速度采样间隔(秒) | | `sim_speed_name_pattern` | `.*-(k1\|t1\|t2)$` | Docker 容器名匹配正则 | 前端监控/合并阈值见 `static/js/ui_limits.js`(与后端独立)。 ## 跨平台说明 进程与 IO 通过 **psutil** 采集;**内存主列**按平台自动对齐本地系统监视器(见 `monitor/platform_memory.py`)。 | 平台 | 进程表主列「内存」 | `memory_private` 字段(DB/曲线副线) | 副列 | |------|-------------------|--------------------------------------|------| | **Linux** | `resident − share`(libgtop 或 statm,≈ 系统监视器 **Memory**) | 同上 | **Resident Memory**(完整常驻) | | **Windows** | 完整 RSS | 专用工作集(任务管理器「内存」) | 专用工作集 | | **macOS** | 完整 RSS | USS | USS | | 能力 | API | 说明 | |------|-----|------| | 进程列表 | `process_iter()` | Win / Linux / macOS | | CPU | `cpu_times()` 差分 ÷ Δt ÷ `cpu_count()` ×100,单进程封顶 100% | 对齐任务管理器「进程」页刻度;合并组为各进程之和(不含 PID 0) | | 内存 | `memory_info()` / `platform_memory` | Linux 主显示为 rss−shared;`memory_rss` 始终为完整 RSS | | 进程 I/O | Win/Linux:`io_counters()`;macOS:`proc_pid_rusage(RUSAGE_INFO_V2)` | 累计读写传输字节按单调时钟差分;Linux/macOS 对应存储字节,Windows 为系统进程 I/O 计数;无权限时为空 | | 网络速率 | Windows:ETW 1 秒事件时间窗;Ubuntu:nethogs/libpcap;macOS:nettop | TCP+UDP、按 PID 汇总;Windows 包含虚拟网卡和显式回环并提供拆分字段。任务管理器使用独立平滑/归属口径,单帧不能直接对比;依赖或权限不足时为 `null`(UI「-」),不填假 0 | ## 常见问题 **Q: Linux 上与系统监视器内存仍不一致?** A: 主列对应 **Memory**(`resident − share`),副列对应 **Resident Memory**。安装 `gir1.2-gtop-2.0` 后与系统监视器同源;未安装时用 statm,数值应接近。若仍差数 MB~数十 MB,多为 **刷新时刻不同**(本工具约 1 秒刷新进程列表)。合并多 PID 时相加仍可能重复计入共享库。 **Q: Linux 上 `pip install` 报 `externally-managed-environment`?** A: 系统 Python 不允许全局 pip 安装。按上文 **Linux** 小节:先 `sudo apt install python3.12-venv python3-full`,再 `python3 -m venv .venv` 与 `source .venv/bin/activate`,然后在虚拟环境里 `pip install -r requirements.txt`。不要使用 `--break-system-packages`。 **Q: 点击开始后长时间显示「启动中」?** A: 需等所有选中 PID 都采到 **CPU + 内存**(状态栏会显示 `启动中 x/y`)。通常约 1~2 秒;若某进程已退出、采样超时或无法读内存,可能一直不满足,请减少选择或去掉无权限进程。无磁盘 IO 的进程不会阻塞启动。 **Q: 合并切换时图表闪一下?** A: v1.3.1 起重建过程有遮罩并批量定轴;若仍异常,请刷新页面后重试。 **Q: SSE 断开?** A: 前端会自动指数退避重连;生产环境请安装 `waitress`,避免 Flask 开发服务器长连接不稳定。 **Q: 网络列一直是「-」?** A: 查看 `/api/config` 的 `net.status` 与 `net.detail`。Windows 需管理员权限开启 ETW;Ubuntu 需安装 `nethogs` 并授予抓包 capability 或以 sudo 启动;macOS 使用系统 `nettop`,若系统隐私策略拒绝访问会显示权限错误。所有平台不可用时均显示「-」,不会填假 0。 **Q: 勾选「监控仿真速度」后提示未发现容器?** A: 需本机 Docker 运行且存在命名形如 `xxxx-k1` / `xxxx-t1` / `xxxx-t2` 的 Booster 虚拟机器人容器。用 `docker ps` 与 `docker port 8788/tcp` 确认 physics 端口已映射。容器重启后宿主机端口会变,请点击 **刷新** 再勾选。 **Q: 仿真速度历史在哪里回放?** A: 点击「加载历史」后,标签栏会出现 **仿真 …** 会话(与进程会话并列);选中即可回放各容器仿真速度曲线,并可导出 `sim_*.log`。 **Q: 磁盘曲线一直为空(macOS)?** A: 系统对非本用户进程的 IO 计数可能受限,属平台限制。 ## 许可证 MIT