Files
MoviePilot/scripts/perf/README.md
T

138 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MoviePilot Docker A/B Harness
该工具用同一个冻结 Docker substrate 对两个 Git commit 做源码级 A/B。派生镜像会先清空
`/app`,复制目标 commit 的完整 `git archive`,再从 substrate 注入镜像构建阶段生成的插件目录、
`sites.*.so``user.sites.v3.bin`。如果依赖或 Docker substrate 输入发生变化,工具会拒绝继续,
避免把外部构建输入漂移误算成性能收益。
工具不会读取工作区或容器内的 `app.env`,不挂载真实配置、媒体目录或 Docker socket。固定配置只使用
内置实验室占位凭据,样本不发布主机端口,并运行在无外网的 internal network。
## 一次性预热浏览器
默认从固定命名 volume `mp-perf-v3-browser-seed` 复制 CloakBrowser 缓存。该 volume 只需联网预热
一次:
```bash
docker volume create mp-perf-v3-browser-seed
docker run --rm \
--mount source=mp-perf-v3-browser-seed,target=/moviepilot/.cloakbrowser \
--entrypoint python3 \
jxxghp/moviepilot-v3@sha256:925de1fdf1bb0312144bc818bc8ebaa999a9a159c6d14f1b48b0ff05edb7f720 \
-m cloakbrowser install
```
也可以在 `seed``run` 时显式传入 `--allow-browser-download`,但该选项会让 seed 阶段联网;
正式 Before/After 样本仍然只克隆预热结果并使用 internal network。
## 分阶段执行
所有全局参数必须放在子命令前。结果默认写到系统临时目录下的
`moviepilot-perf-results/<campaign>/`
```bash
PYTHON=../.venv/bin/python
CAMPAIGN=v3-perf-001
${PYTHON} scripts/perf/moviepilot_docker_ab.py \
--campaign "${CAMPAIGN}" \
build --before-ref upstream/v3 --after-ref HEAD
${PYTHON} scripts/perf/moviepilot_docker_ab.py \
--campaign "${CAMPAIGN}" \
seed
${PYTHON} scripts/perf/moviepilot_docker_ab.py \
--campaign "${CAMPAIGN}" \
sample --variant before --index 1 --points 1,5,10,30
```
开发 harness 时可以用小数分钟做短冒烟,例如 `--points 0,0.02`。正式数据必须保持
`1,5,10,30`
未指定 `--scenario` 时仍使用 `idle-default`,样本目录和 Docker 资源名称与既有命令保持一致。
## 浏览器激活场景
浏览器场景使用 campaign browser seed 的独立克隆卷,不直接挂载或写入固定来源卷,也不会在样本
阶段下载浏览器。容器保持 internal network;探针只发送信号,`app.sdk.browser` 的导入、浏览器上下文
创建和本地 `data:` 页面校验都发生在主 MoviePilot Python 进程中。
非默认浏览器场景用于候选实现的 After 激活门禁;Before 不具备新 SDK,且旧实现启动时已经常驻
Xvfb,因此不能用同一个 `0 → 0` / `0 → 1` 不变量衡量。三轮 Before/After 空载收益仍由默认
`run``idle-default` 场景完成,浏览器场景用三个隔离的 After sample 记录冷激活成本。
```bash
../.venv/bin/python scripts/perf/moviepilot_docker_ab.py \
--campaign v3-perf-002-headless \
sample --variant after --index 1 --scenario browser-headless --points 1,5,10,30
../.venv/bin/python scripts/perf/moviepilot_docker_ab.py \
--campaign v3-perf-002-headed \
sample --variant after --index 1 --scenario browser-headed --points 1,5,10,30
```
- `browser-headless`:一次真实 headless context 激活,要求 Xvfb `0 → 0`
- `browser-headed`:主进程内两个线程通过屏障并发调用
`launch_browser_context(headless=False)`;要求两个真实 SDK 冷启动调用成功、额外上下文关闭后只保留一个、
Capability observation 只有一个 `headed_browser_launch` generation/start,且 Xvfb `0 → 1`
- 激活完成后再开始 `1/5/10/30m` 计时,JSON 保留激活前后 Engine 网络、working set、进程
PSS/USS/RSS/线程、Xvfb 数量/PSS、`sys.modules` 和进程内 marker
- 非默认场景结果保存在 `samples/<scenario>/<variant>-<index>/`,可与同 campaign 的 idle 样本并存,
Markdown 中位数会按场景分组,不会混算。
## 完整三组 A/B
```bash
../.venv/bin/python scripts/perf/moviepilot_docker_ab.py \
--campaign v3-perf-001 \
run \
--before-ref upstream/v3 \
--after-ref HEAD \
--points 1,5,10,30
```
执行顺序固定为:
```text
Before-1 → After-1 → After-2 → Before-2 → Before-3 → After-3
```
每个样本都从 SQLite 和浏览器 seed 克隆新的命名 volume。样本结束后立即移除容器和样本卷;
完整 `run` 结束后还会移除 campaign seed 与 internal network。派生镜像和本地结果保留,便于复核。
## 输出
```text
<output>/<campaign>/
├── build.json
├── seed.json
├── results.json
├── report.md
└── samples/
├── before-1/
│ ├── result.json
│ ├── container.log
│ └── modules/
└── ...
```
- `results.json`Engine stats、进程 PSS/USS/RSS/线程、网络累计值和模块前缀计数;
- `report.md`:三次原值与中位数 Before/After 汇总;
- `modules/`:由目标 MoviePilot Python 进程自身写出的完整 `sys.modules` 名称清单;
- `container.log`:已移除实验室凭据值和本地实例 UUID。
容器 working set 统一按 Docker Engine API 的
`memory_stats.usage - memory_stats.stats.inactive_file` 计算。进程 PSS 仅用于归因,不能替代容器指标。
## 清理
清理严格限定到 campaign 标签;不会执行 Docker prune
```bash
../.venv/bin/python scripts/perf/moviepilot_docker_ab.py \
--campaign v3-perf-001 cleanup --images
```
本地 JSON、Markdown 和日志不会被 `cleanup` 删除。