- /api/assets/ 列表 select_related('origin_task__project') 为解析资产归属商品,
会把每个资产关联 AITask 的 request_payload/response_payload(完整 AI 请求/响应 JSON)
整行拖出 → 取全部 200 资产实测 >60s 超时,数据越多越慢(用户报的「刷新越来越卡」)。
加 .defer 这两列后 0.76s,product 仍正常解析、序列化 0 额外查询。
- billing/ledgers 同模式补 .defer(task payload)。ai/billing.summary 早已 defer,assets/ledgers 本是漏网。
- 附 qa/function-audit/perf-probe.mjs 性能验证闸 + PERF-GATE.md(API 确定性断言+浏览器功能守护)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.9 KiB
3.9 KiB
AirShelf/core 性能验证闸(perf-probe)
给 ralph-loop(或人工)当 pass/fail 闸用的性能回归探针。全绿 → 退出码 0;任一硬闸不过 → 退出码 1 + PERF-PROBE: FAIL。
一句话目的
逐页 + 逐接口验证「访问变快了 / 重复请求没了 / 但功能没改崩」。改性能时反复跑它,直到全绿。
怎么跑
先起前后端(后端 :8010 连真实 MySQL;前端 vite dev 必须带 /api 代理):
# 后端(backend/)
DB_ENGINE=mysql .venv/bin/python manage.py runserver 127.0.0.1:8010 --noreload
# 前端(frontend/)—— 记下它实际监听的端口(可能是 5173/5174)
npm run dev
# 探针(qa/function-audit/)
node perf-probe.mjs --base http://127.0.0.1:5174 # 改成前端实际端口
node perf-probe.mjs --base http://127.0.0.1:5174 --only dashboard,projects
node perf-probe.mjs --base http://127.0.0.1:5174 --headed # 看着跑
默认演示账号 e2e-20260529-0806@airshelf.test / demo12345;也可 --token <TOKEN> 免登录。
闸怎么判(两层)
硬闸(确定性,挂 pass/fail)
- API 级:列表接口必须遵守
page_size——?page_size=200要全部一页拉得到时,next必须为null、条数 =count。 当前根因:/api/assets/无视page_size=200,死按 20 条/页返回 → 前端allAssets被迫并行翻 N 页(资产越多页越多)。 - 浏览器级:任意页面不得出现资产分页瀑布(
/api/assets/?page=2…)。这是上面那条的直接症状。 - 功能守护:每页必须真渲染(没掉回登录页)、所有接口
< 400、bootstrap 必须在 25s 内发起(否则=后端慢到没加载出来,判失败防假通过)。
为什么 API 检查 + 浏览器双保险:浏览器按时序数瀑布会被后端延迟抖动影响(慢时漏抓)。API 断言与时序无关、永不抖,是真正的硬闸;浏览器只作功能守护 + 佐证。
软提示(打印不挂闸,留给架构决策)
- 接口延迟:本地连远程 MySQL 每次握手 ~1.6s,绝对 ms 天然抖,不宜当硬闸;但打印出来暴露疑似 N+1 的慢接口(基线里
/api/projects/~2s、/api/ops/notifications/~1.4s,大概率缺select_related/prefetch_related)。 - 首屏接口数超预算:每页 bootstrap 拉了 ~9 个全局接口(products/projects/assets/billing/trend/members/models/tasks/notifications),且每个路由都重拉一遍——连
/account这种用不到的页也拉。这是架构性过量拉取,怎么改属设计决策(懒加载 / 按页取数 / 引入 react-query 缓存层),不由闸强判,见下。
基线(2026-06-17,优化前)
- ❌
/api/assets/page_size 未生效(count=194 → 返回 20、next 有)→ 根因。 - ❌ dashboard / projects / account 等出现 9 页资产瀑布。
- ⚠
/api/projects/~2s、/api/ops/notifications/~1.4s(疑似 N+1)。 - ⚠ 每页首屏 9~18 个接口(bootstrap 每页重拉)。
- ✅ 全部页面功能正常、无接口报错。
优化方向(供参考,不替代设计决策)
- 修
page_size根因(后端):让/api/assets/真正应用AssetPagination(max_page_size=200)。这一条修好,前端瀑布自动消失。 - 修
allAssets兜底(前端src/api.ts):别用results.length反推页数;按count+ 真实page_size算,或直接跟next。 - 慢接口补 ORM:
/api/projects/、/api/ops/notifications/等加select_related/prefetch_related、确认有分页。 - (设计决策)bootstrap 瘦身:全局只加载真正全站要用的;各页数据按需懒加载 + 缓存,避免每路由重拉 9 个接口。此项请人工拍板方案再做。
给 ralph 的硬规矩
- 严禁删功能换性能;严禁为过闸放宽断言阈值或把检查注释掉。
- 每轮改完必须重跑
node perf-probe.mjs --base <前端端口>,全绿(PERF-PROBE: PASS)才算完成。 - 改后端任务/接口代码后注意:本地不起 worker,纯接口改动 runserver 即时生效。