feat: publish Dever core with project scaffolding and versioned AI skills
This commit is contained in:
1 parent
70fa73cdc2
commit
ac458ffa7f
960 files changed
+221319
-1163
No files matched your search
@@ -0,0 +1,3 @@
|
||||
{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"检查 HTTP/2 配置与运行时公开合同一致"}
|
||||
{"file":".trellis/spec/backend/quality-guidelines.md","reason":"检查测量公平性、计数完整性、资源预算和验证范围"}
|
||||
{"file":".trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md","reason":"核对实现是否真正拆分物理连接和并发流"}
|
||||
@@ -0,0 +1,84 @@
|
||||
# 设计
|
||||
|
||||
## 1. 边界与复用
|
||||
|
||||
继续使用 `test/performance` 的“构建与测量分离”结构:`build.py` 只生成并指纹化产物,`run.py` 只启动清单内的二进制并采样。进程、cgroup、直方图、逐 case 落盘和失败保留逻辑全部复用。新增的唯一核心抽象是 HTTP 连接拓扑:
|
||||
|
||||
```text
|
||||
ConnectionShape
|
||||
physical_connections
|
||||
streams_per_connection
|
||||
request_slots = physical_connections * streams_per_connection
|
||||
```
|
||||
|
||||
HTTP/1.1 要求 `streams_per_connection = 1`;HTTP/2 要求复用连接。这个模型避免继续把并发请求与 TCP 连接混为一个 `connections` 参数,也让报告能解释吞吐和内存差异来自哪里。
|
||||
|
||||
## 2. Rust 基准对端与负载端
|
||||
|
||||
`network_bench` 的统一负载入口调整为:
|
||||
|
||||
```text
|
||||
network_bench load h1|h2 URL PATH RATE SECONDS PHYSICAL_CONNECTIONS STREAMS_PER_CONNECTION TIMEOUT_MS REUSE CA
|
||||
```
|
||||
|
||||
所有仓库调用者一次性迁移,不保留第二套旧参数解析。
|
||||
|
||||
- HTTP/1.1 保留现有“一名 worker 独占一条连接”的实现,并要求 streams 为 1。
|
||||
- HTTP/2 在计时前主动建立指定数量的物理连接;每条连接由 Hyper HTTP/2 client driver 持有,`SendRequest` 按该连接的请求槽克隆给 worker。总 worker 数为 shape 的乘积,worker 固定映射到连接,不额外建立连接。
|
||||
- HTTP/2 连接中断后不重试请求或静默补建连接。失败必须进入错误计数,避免恢复逻辑污染吞吐数据。
|
||||
- 两种协议共享现有速率调度、队列、响应校验、延迟直方图和结果守恒逻辑,不复制 metrics/validation。
|
||||
- 结果新增 `http_version`、`physical_connections`、`streams_per_connection`、`request_slots` 和 `successful_handshakes`。H2 的握手数必须等于物理连接数。
|
||||
|
||||
H2 请求使用完整 scheme/authority/path 和 `Version::HTTP_2`。明文使用 prior knowledge;TLS client/server 配置按协议派生 ALPN,H2 只允许 `h2`,不改变运行时用于 WSS 的共享 TLS 配置。
|
||||
|
||||
服务模式新增 `runtime-http2`、`runtime-https2`、`hyper-http2`、`hyper-https2`。`ServiceKind` 集中派生 runtime/TLS/H2 三个维度,避免模式分支散落。直接 runtime 使用 `Http2Limits`;原生 Hyper 使用 `http2::Builder<TokioExecutor>`,显式配置与 N5 相同的 streams、窗口、header/frame/send-buffer 上限。两者继续复用同一响应路由和连接生命周期。
|
||||
|
||||
## 3. Dever 夹具与构建清单
|
||||
|
||||
HTTP 夹具暴露 `http`、`https`、`http2`、`https2` 四个入口。`serve` 接收 `dever.http.Limits` 参数,四个 worker 只负责选择 TLS 和协议配置,避免复制路由与关闭流程。
|
||||
|
||||
`build.py` 增加 HTTP/2 构建参数并写入 manifest:
|
||||
|
||||
- `http2_streams = 16`
|
||||
- `http2_stream_window_bytes = 65535`
|
||||
- `http2_connection_window_bytes = 262144`
|
||||
|
||||
`config.dever` 分别生成 HTTP/1.1 和 HTTP/2 limits;`task_capacity` 继续按有界并发计算,并校验正式拓扑的总请求槽不超过语言上限。旧产物目录和报告不修改,新构建必须使用新的输出目录。
|
||||
|
||||
## 4. Python 运行器
|
||||
|
||||
新增两个显式 suite:
|
||||
|
||||
- `http2`:吞吐、延迟与活跃资源矩阵。
|
||||
- `http2-recovery`:同一服务进程上的多轮连接建立、请求和断开。
|
||||
|
||||
`--http2-connections` 接受物理连接档位,默认 `1,4`;每连接流数从 manifest 读取。`--implementations` 可将 smoke 或 64 MiB 场景限制为 `dever`,正式矩阵默认为 `dever,runtime,hyper`。已有 `http` suite 的 `--concurrency` 和连接新建/复用语义不变。
|
||||
|
||||
吞吐 case 的流程为:启动服务并取得 READY,运行独立 warmup,等待连接释放并采样基线,运行正式负载,同时采样服务端与客户端;负载退出后再次采样以记录 FD/RSS 回落。case 名和 JSON 主键包含实现、传输、路径、速率、物理连接、每连接流和 repeat,避免结果覆盖或混淆。
|
||||
|
||||
恢复 case 使用独立参数 `--recovery-connections`、`--recovery-rate`、`--recovery-path`,复用 `--cycles` 与 `--duration`。每轮启动一次负载进程,在同一服务上建立固定 shape,完成请求后关闭连接;运行器等待稳定窗口并保存该轮末样本。FD 不回到 READY 基线、请求错误、握手数不符或服务提前退出均使 case 失败。RSS 只报告趋势,不以“没有立即回到启动值”单独判断泄漏。
|
||||
|
||||
报告继续保留 `cases.jsonl` 和 `report.json`,并在完整或部分结果上生成结构化 `summary`。摘要按实现、协议、TLS、路径、速率和 topology 分组,对成功 QPS、p99、RSS/PSS/FD 峰值取各 repeat 中位数;不把不同 offered rate 或饱和/未饱和 case 混合。
|
||||
|
||||
## 5. 测量矩阵
|
||||
|
||||
正式测量固定服务端 1 worker、1 CPU、128 MiB cgroup、swap=0;客户端绑定另一 CPU且位于服务预算之外。每组 0.5 秒预热、2 秒正式负载、3 个独立服务进程 repeat:
|
||||
|
||||
| 正文 | offered rate | topology | 实现 | 传输 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `/plain` 5 B | 5k / 15k / 30k req/s | 1x16、4x16 | Dever/runtime/Hyper | h2c、TLS+h2 |
|
||||
| `/bytes` 64 KiB | 100 / 500 / 1k req/s | 1x16、4x16 | Dever/runtime/Hyper | h2c、TLS+h2 |
|
||||
|
||||
另运行 10 轮、1x16、`/plain` 的恢复矩阵,以及 64 MiB 下 Dever 的 1x16 明文/TLS 活跃代表场景。若当前机器不能创建指定 cgroup,工具必须明确失败;不得回退为无预算结果后仍标记完成。
|
||||
|
||||
## 6. 解释与决策
|
||||
|
||||
- 主要比较同一 H2 topology 下 Dever、runtime 和 Hyper 的差异,定位语言桥接、运行时结构化任务和底层协议栈各自成本。
|
||||
- 1x16 与 4x16 比较多路复用和多物理连接扩展;它们不是“连接数相同”的横向比较。
|
||||
- `/bytes` 的速率按响应字节量降低,避免只测客户端或 loopback 带宽耗尽;65536 字节正文会越过 65535 字节默认单流窗口,可观察 WINDOW_UPDATE 路径。
|
||||
- `dropped_capacity` 表示负载端无法在计划时间取得请求槽,不算服务错误;分析时必须同时看 actual QPS、请求延迟和服务 CPU,不能只看 offered rate。
|
||||
- 不设预定胜负线。若 Dever 相对 direct runtime 出现稳定的大幅差距,或内存随 recovery 周期持续增长,则把证据和复现命令交给后续独立优化任务。
|
||||
|
||||
## 7. 回退形态
|
||||
|
||||
本阶段不迁移生产 API。若 H2 基准实现无法通过独立 smoke,删除新增 suite、服务模式和夹具入口即可回到原有 H1 基准;历史产物目录不受影响。任何正式测量都写入新的 `target/performance/*` 目录,失败结果保留且不覆盖旧报告。
|
||||
@@ -0,0 +1,3 @@
|
||||
{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"HTTP/2 streams、窗口、ALPN、结构化任务和资源预算合同"}
|
||||
{"file":".trellis/spec/backend/quality-guidelines.md","reason":"独立二进制基准、cgroup、报告和定向验证规则"}
|
||||
{"file":".trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md","reason":"现有 H1 基准限制、锁定 Hyper API 和 H2 负载模型结论"}
|
||||
@@ -0,0 +1,50 @@
|
||||
# 执行计划
|
||||
|
||||
## 1. 任务启动
|
||||
|
||||
- [x] 用户审核本 PRD、设计和执行计划后,运行 `task.py start`;启动前不改产品或基准源码。
|
||||
- [x] 使用 `trellis-before-dev` 重新加载 backend 规范,核对工作区状态和已有性能产物,不清理用户文件。
|
||||
|
||||
## 2. 基准协议模型
|
||||
|
||||
- [x] 在 `network_bench` 中加入 `h1|h2` 与 `ConnectionShape` 参数校验;H1 限制每连接一槽,H2 限制复用且乘积有界。
|
||||
- [x] 保留一个速率调度和 metrics 路径;把 H1 独占连接与 H2 共享 sender 封装为两个小的协议执行分支,不引入通用 trait 层级。
|
||||
- [x] H2 计时前建立固定数量物理连接,按连接分配 sender clone,关闭时排空/终止 driver;不重试、不自动扩容。
|
||||
- [x] 在结果中输出并校验协议、shape 和握手计数,继续保证全部请求计数守恒和完整正文校验。
|
||||
|
||||
## 3. 三类服务实现
|
||||
|
||||
- [x] 扩展 `ServiceKind` 和 TLS ALPN 派生,新增 runtime/raw Hyper 的 h2c 与 TLS+h2 模式。
|
||||
- [x] direct runtime 与 raw Hyper 使用相同的 streams、窗口、header/frame/send-buffer 约束;复用响应路由、accept 限额和关闭流程。
|
||||
- [x] 重构 Dever HTTP fixture,让四个入口共享 serve/route/lifecycle,只在入口选择协议和 TLS。
|
||||
- [x] 扩展构建配置与 manifest,生成并指纹化 `http2`、`https2`,保留 H1 产物。
|
||||
|
||||
## 4. 运行器与摘要
|
||||
|
||||
- [x] 增加 `http2`、`http2-recovery` suite、物理连接档位、实现筛选及恢复参数,并按 manifest 校验 capacity、streams 和窗口。
|
||||
- [x] HTTP/2 吞吐 case 记录 warmup、正式负载、断开后样本、服务/客户端资源和 cgroup 状态;case 标识包含完整维度。
|
||||
- [x] 恢复 case 在一个服务进程内运行多轮固定 shape,逐轮校验请求和握手并记录 FD/RSS 回落。
|
||||
- [x] 从逐 case 结果生成分组中位数 summary;失败时仍保存已完成 case 和可诊断日志。
|
||||
|
||||
## 5. 定向验证
|
||||
|
||||
- [x] 运行 `python3 -m unittest discover -s test/performance -p 'test_runner.py' -v`,覆盖参数、计数、summary、进程回收和错误路径。
|
||||
- [x] 离线 release 构建 `network_bench`,运行现有独立 Python H1 对端测试,确认一次性 CLI 迁移没有改变 H1 测量语义。
|
||||
- [x] 运行 H2 loopback smoke,覆盖 1 条物理连接、至少 16 个请求槽、明文/TLS、`/plain`/`/bytes`、三类服务模式和错误正文拒绝。
|
||||
- [x] 用新的输出目录构建 Dever 性能夹具,核对 manifest 指纹、HTTP/2 limits 和四个 HTTP 入口。
|
||||
- [x] 运行最小 `http2`/`http2-recovery` runner smoke,检查失败报告、FD 回落和原始计数完整性。
|
||||
|
||||
## 6. 有界正式测量
|
||||
|
||||
- [x] 先确认可用 CPU affinity、cgroup v2 cpu/memory 控制器、磁盘和已有服务边界,再说明将执行的有界命令。
|
||||
- [x] 运行 128 MiB `/plain` 矩阵:5k/15k/30k,1x16/4x16,三实现、h2c/TLS、3 repeats。
|
||||
- [x] 运行 128 MiB `/bytes` 矩阵:100/500/1000,1x16/4x16,三实现、h2c/TLS、3 repeats。
|
||||
- [x] 运行 128 MiB 10 轮恢复矩阵,并运行 64 MiB Dever 1x16 明文/TLS 活跃场景。
|
||||
- [x] 核对全部报告 status、errors、dropped、OOM、FD、RSS/PSS、CPU 和摘要分组;不以单次异常样本下结论。
|
||||
|
||||
## 7. 收尾审查
|
||||
|
||||
- [x] 更新 `test/performance/README.md` 和 `.trellis/spec/backend/quality-guidelines.md` 的 CLI、矩阵、实测结果和边界说明。
|
||||
- [x] 检查最终改动是否仍有重复协议分支、混合职责或无必要依赖;确认未修改生产运行时、旧报告和用户文件。
|
||||
- [x] 运行任务 JSONL 校验、Python 语法检查及受影响的最小回归;不运行全量测试。
|
||||
- [x] 记录实际通过、失败、跳过和不可用项;完成 Trellis 检查与会话记录,不提交 Git。
|
||||
@@ -0,0 +1,40 @@
|
||||
# HTTP/2 性能基准
|
||||
|
||||
N5 已完成 HTTP/2 服务端、客户端和连接池的功能接入,但现有独立二进制基准仍只测 HTTP/1.1。当前阶段为 HTTP/2 建立可重复的小机器性能证据,不凭功能测试或理论值宣称性能提升。
|
||||
|
||||
## 需求
|
||||
|
||||
- 扩展现有显式运行的独立二进制基准,新增 HTTP/2 suite;保留已有 HTTP/1.1、异步和长连接基准的语义及历史报告。
|
||||
- 覆盖明文 prior knowledge 和 TLS ALPN 两种 HTTP/2 传输,统一比较原生 Dever 程序、直接 `dever-runtime` 和原生 Hyper 三种实现。
|
||||
- 负载模型必须把物理 TCP 连接数与每连接并发流数分开。每个报告明确记录协议、TLS、物理连接数、每连接请求槽、总请求槽、服务端流/窗口配置和正文大小。
|
||||
- 至少覆盖单连接多流和多连接多流;请求必须校验状态码、Content-Type 和完整正文,所有计划、发送、完成、失败及丢弃请求均可核对。
|
||||
- 记录实际成功吞吐、总延迟/排队延迟/请求延迟的 p50/p95/p99,以及服务端和客户端 RSS、PSS、峰值、线程、FD、CPU 和 cgroup 内存/OOM 数据。
|
||||
- 同一服务进程上重复建立、使用和关闭 HTTP/2 连接,记录每轮断开后的 FD/RSS 差值,验证物理连接能够回收且内存不按轮持续增长。
|
||||
- 生成按实现、传输、路径、速率和连接拓扑分组的中位数摘要,同时保留逐 case 原始样本和失败时已完成的数据。
|
||||
- 完成 1 worker、1 服务 CPU、128 MiB、无 swap 的正式矩阵,并完成 64 MiB 下的 Dever 活跃 HTTP/2 代表场景;负载端使用独立 CPU且不计入服务预算。
|
||||
|
||||
## 约束
|
||||
|
||||
- 本任务只改基准夹具、基准对端、运行器、定向测试和对应性能文档;不修改 `crates/dever-runtime`、编译器或语言公共 API。基准揭示的生产瓶颈另建优化任务,避免边测边改导致基线失效。
|
||||
- 复用仓库锁定的 Hyper 1.11.1、h2 0.4.19、rustls 和现有进程/cgroup 采样器,不引入新的协议栈或压测依赖。
|
||||
- HTTP/2 明文只使用 prior knowledge;TLS 只协商 `h2`,不降级 HTTP/1.1。HTTP/1.1 每连接请求槽固定为 1,HTTP/2 只测复用连接,不测每请求新建连接。
|
||||
- 服务端与客户端固定使用 N5 默认值:每连接 16 流、65535 字节单流接收窗口、262144 字节连接接收窗口,以及运行时已有的 16 KiB frame/send-buffer 上限。
|
||||
- `/plain` 用于小响应调度和协议开销,`/bytes` 使用 65536 字节正文并跨越默认单流窗口;`/json` 不进入正式矩阵,因为当前夹具只返回预制 JSON,信息与小响应重复。
|
||||
- 不设与机器无关的绝对 QPS 或内存门槛。错误、OOM、计数不守恒和 FD 未回落属于失败;容量丢弃与相对性能只作为结果,不伪装成通过或失败阈值。
|
||||
- 仅运行本任务的 Python 单元测试、独立 loopback smoke、必要的离线 release 构建和显式有界性能命令;不运行全量测试,不替换全局二进制,不接触已有服务,不提交 Git。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] HTTP/1.1 旧入口仍通过现有独立 Python 对端测试;HTTP/2 smoke 证明一条实际物理连接承载至少 16 个并发请求槽,明文和 TLS 均完整成功。
|
||||
- [x] 构建清单包含 `http2`/`https2` Dever 产物、HTTP/2 配置及所有二进制指纹;运行阶段只使用清单中的已构建产物。
|
||||
- [x] `http2` suite 覆盖三种实现、两种传输、`/plain` 与 `/bytes`、`1 x 16` 与 `4 x 16` 两种拓扑,并保存可核对的逐 case 数据与聚合摘要。
|
||||
- [x] `http2-recovery` suite 在同一服务进程上完成至少 10 轮连接周期;每轮请求正确,断开后 FD 回到 READY 基线,且报告保留 RSS 变化序列。
|
||||
- [x] 128 MiB 正式矩阵中无请求错误、无 OOM;丢弃请求如实报告。64 MiB 代表场景无 OOM,并报告峰值而非只报告进程 RSS。
|
||||
- [x] 文档写明运行命令、环境、矩阵、限制和实测结论;不得将 HTTP/2 结果外推为所有后端负载或真实网络的性能保证。
|
||||
- [x] 定向测试覆盖参数校验、计数守恒、连接拓扑字段、摘要分组、H2 明文/TLS 正文校验、进程失败和连接回收;相关检查全部通过。
|
||||
|
||||
## 排除项
|
||||
|
||||
- RFC 8441 WebSocket-over-HTTP/2、h2c Upgrade、HTTP/3、服务器推送、非空 trailers、HTTP/2 客户端自动重试。
|
||||
- 小时级 soak、跨主机网络、丢包/限速故障注入、真实公网站点和多平台硬件矩阵。
|
||||
- 本阶段根据一次测量直接改写运行时热路径或承诺固定的 Fiber/Go 对比数字。
|
||||
@@ -0,0 +1,31 @@
|
||||
# 现有基准与 HTTP/2 API 调研
|
||||
|
||||
## 现有结构
|
||||
|
||||
- `test/performance/build.py` 负责生成 Dever fixtures、复制 Rust peers、记录配置和 SHA-256;`run.py` 只执行已指纹化产物。这一分离可直接复用。
|
||||
- 当前 HTTP suite 覆盖 Dever、direct runtime、raw Hyper,但三者都只使用 HTTP/1.1。`config.dever` 明确写入 `http2 = null`。
|
||||
- 当前 loader 的 `connections` 同时决定 worker 数和连接数,每个 worker 串行持有一条 HTTP/1.1 连接;它无法证明 HTTP/2 多路复用。
|
||||
- 现有 runner 已有固定速率调度、三类延迟直方图、进程 RSS/PSS/FD/CPU 采样、cgroup memory/peak/OOM 采样、逐 case 落盘和异常清理,不应重写。
|
||||
- `live` suite 已有多轮连接后 FD/RSS 差值的报告方式,可复用其 phase 后采样语义,但 HTTP/2 负载和连接创建应继续由 `network_bench` 负责。
|
||||
|
||||
## N5 已有合同
|
||||
|
||||
- `Http2Limits` 的公开维度为 streams、stream window 和 connection window;默认分别为 16、65535、262144。
|
||||
- cleartext HTTP/2 使用 prior knowledge;TLS 配置必须协商 `h2`,不能降级或影响 WSS 的 HTTP/1.1 TLS 配置。
|
||||
- 客户端按流租约复用物理连接,服务端连接和流均受限;固定 16 KiB frame/send-buffer,关闭自适应窗口。
|
||||
- `/bytes` fixture 为 65536 字节,恰好跨过默认 65535 字节单流窗口,适合覆盖 flow-control 热路径。
|
||||
|
||||
## 锁定依赖可用能力
|
||||
|
||||
- Cargo.lock 固定 Hyper 1.11.1、h2 0.4.19、rustls 0.23.44 和 tokio-rustls 0.26.5,不需要新依赖。
|
||||
- Hyper HTTP/2 `SendRequest` 实现 `Clone`,可让多个请求 worker 共享同一物理连接的 driver。
|
||||
- Hyper HTTP/2 client/server builder 可显式设置 initial stream/connection window、adaptive window、max concurrent streams、max frame、max send buffer 和 header list size。
|
||||
- Hyper HTTP/2 request future 的取消会对单流发送 RST_STREAM;基准不需要自己实现帧协议。
|
||||
|
||||
## 设计结论
|
||||
|
||||
1. 物理连接与请求槽必须拆开;只给现有 loader 换 HTTP/2 handshake 会得到错误的“一 worker 一连接”模型。
|
||||
2. H2 连接应在计时前主动建立,worker 固定映射到已建 sender;这样报告的物理连接数由 loader 自己控制和证明。
|
||||
3. H1 和 H2 共享调度、计数和响应校验,但连接执行策略分开。不存在足够稳定的公共行为值得引入 trait 或继承式抽象。
|
||||
4. raw Hyper 对照必须显式复制 N5 的协议参数;使用 Hyper 默认值会把配置差异误判为 Dever/runtime 开销。
|
||||
5. 性能任务不同时修改生产 runtime。测量发现的瓶颈需要在固定基线后另立任务验证,否则优化前后结果不可复现。
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "http2-performance",
|
||||
"name": "http2-performance",
|
||||
"title": "HTTP/2 performance benchmarks",
|
||||
"description": "扩展现有独立二进制基准,测量小内存下 HTTP/2 多路复用的吞吐、尾延迟、内存和连接回收。",
|
||||
"status": "completed",
|
||||
"dev_type": null,
|
||||
"scope": "test/performance + test/dever-tests/examples/network_bench* + performance docs/spec",
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "Antigravity",
|
||||
"assignee": "Antigravity",
|
||||
"createdAt": "2026-09-12",
|
||||
"completedAt": "2026-09-13",
|
||||
"branch": "main",
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": "09-04-dever-language-mvp",
|
||||
"relatedFiles": [],
|
||||
"notes": "HTTP/2 benchmark complete: 224 formal cases plus 60 recovery cycles, fixed 1x16/4x16 topology, h2c/TLS and Dever/runtime/Hyper comparisons. All request errors, OOM and FD deltas were zero; 64 MiB active Dever cases passed. Sixteen runner tests, three loopback tests, release cargo check, Dever fmt-check and independent review passed. No full suite, Rustfmt/Clippy, commit or archive.",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in new issue
Block a user