From f6e55c5c7e7ce1e1a2956a4f6a55683f90ac2926 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Tue, 3 Nov 2026 00:19:40 +0800 Subject: [PATCH] =?UTF-8?q?docs(build):=20=E4=BF=AE=E6=AD=A3=E4=B8=89?= =?UTF-8?q?=E5=A4=84=E3=80=8C=E6=96=87=E6=A1=A3=E8=AF=B4=E6=B3=95=E4=B8=8E?= =?UTF-8?q?=E5=AE=9E=E6=B5=8B=E4=B8=8D=E7=AC=A6=E3=80=8D=E7=9A=84=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=EF=BC=88M96=20=E5=A4=8D=E5=AE=A1=20P2-1/2/3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 只改措辞与注释,**profile 数值一个没动**(release.package 仍是 opt-level="z" + cu16, fast 仍是 opt-2/thin/cu16/unwind)。 P2-1 `panic = "unwind"` 的理由原本写错了:原注释说「漏了这一行 `cargo test --profile fast` 起不来(test harness 依赖 unwind)」。实测三连否掉:`cargo build --profile release -v` 的 rustc 参数里**有** `panic=abort`、`--profile fast` 里没有(这行确实生效,可作证据);但 `cargo test --profile release -p unlucky-i18n --no-run`(abort 档)照样 Finished 并产出测试 二进制,`-v` 里 test 单元**没有** `-Cpanic=`,真跑 23 个测试全过 —— cargo 对 test 目标自己强制 unwind。所以理由改成「让 fast 档编出来的**二进制**走 unwind」,并把「能跑 cargo test」明确标为 **没有区分度**的证据。顺带记下 fast 继承 `strip="symbols"` ⇒ 能 unwind 但没有符号回溯。 P2-2 `[profile.fast.package."*"]` 的注释把机制说反了:原注释说「package 覆盖按 profile 分别 生效,release 的不影响 fast」。实测删掉这块后,fast 档的**外部依赖**直接变成 `opt-level="z"` (`slotmap`:1 那次 3 个单元 opt-2 → 删除后 3 个单元 opt-z),说明 `inherits` 会把 release 的 package 覆盖一起带过来。所以这块是**承重墙**,删了依赖会静默退回 z。注释按实测重写。 P2-3 「收益全在 `codegen-units = 16`」删掉:三组数据的唯一自变量是 opt-level(两臂都是 cu16), cu1→cu16 的收益本轮**没有同条件对照**,已明确标成未测、留待后续归因。同时补一句:GUI 相对旧 基线 +12.9% 里「代码增长」与「依赖 cu16」未分离(ull 只 +1.7%,在 +1~3% 口径内)。 注:P2-1 那条原始错误表述来自 tower 的 mission 任务书,不是 worker 的臆造。 验证:`cargo build --release --bins` rc=0(16m21s,产物字节与 §7.1 记录完全一致: 6,256,128 / 13,910,528 / 16,479,232),`cargo metadata` 通过,README 仍为 400 行(未破门禁)。 --- Cargo.toml | 23 ++++++++++++++--------- packaging/README.md | 34 +++++++++++++++++----------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e6c4180..faf86d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,8 +116,12 @@ strip = "symbols" # 全程序串行链接(375 个 crate 排队),一次性吃掉十几分钟。 # - codegen-units = 16:给 codegen 留并行度,不再把整个 crate 挤成一个 CGU。 # - opt-level = 2:介于 "z" 与 3 之间,"z" 会为了体积关掉一批循环/内联优化,代价是运行期。 -# - panic = "unwind":**必须显式写**。release 是 panic = "abort",inherits 会照抄下来, -# 而 test harness 依赖 unwind —— 漏了这行 `cargo test --profile fast` 直接起不来。 +# - panic = "unwind":release 是 panic = "abort",inherits 会照抄。留着它是为了让 fast 档编出来的 +# **二进制**走 unwind(panic 会栈展开,不是直接 abort)。 +# ⚠️ 理由不是「不写就跑不了测试」:`cargo test` **不**依赖这一行 —— cargo 对 test 目标自己强制 +# unwind。实测 `cargo test --profile release -p unlucky-i18n`(release = abort 档)照跑,23 个 +# 测试全过,且 test 单元的 rustc 参数里**没有** `-Cpanic=`。别拿「cargo test 能跑」当这行生效的证据; +# 要看就用 `cargo build --profile {fast,release} -v` 比 rustc 参数:release 有 `panic=abort`,fast 没有。 # # ⚠️ 定位(实测,别误读):本机(12 核 + 机械盘源码盘 + -j 4)冷编译 fast = 24m27s, # **比 release 的 16m01s 还慢**,体积是 2.3 倍(36.41 vs 15.72 MiB GUI)。瓶颈在两个大 @@ -132,19 +136,20 @@ panic = "unwind" # P6(M96):依赖不需要为体积做极致优化,但**实测结论与直觉相反**——把依赖的 opt-level 从 # release 的 "z" 抬到 3(本档最初就是这么定的)会让冷编译**更慢**、体积还更大: -# 同机冷编译 opt-3 = 22m45s / 19.46 MiB(GUI),opt-"z" = 16m01s / 15.72 MiB。 -# 真正的收益全在 `codegen-units = 16`(并行 codegen),与 opt-level 无关;抬等级是在拿编译时间 -# 和体积换运行期。所以这里**只放宽并行度,opt-level 保持 "z"**,workspace 自己的 crate 仍吃 -# opt-level = "z" / 单 CGU。 +# 同机冷编译 opt-3 = 22m45s / 19.46 MiB(GUI),opt-"z" = 16m01s / 15.72 MiB(两臂同为 cu16)。 +# 所以这里**opt-level 保持 "z",只把并行度放到 16**;workspace 自己的 crate 仍吃 "z" / 单 CGU。 +# ⚠️ **未测**:cu1 → cu16 的收益本轮没有同条件对照(两臂都是 cu16,唯一自变量是 opt-level), +# 所以「cu16 才是收益来源」不是实测结论,要归因得单独跑一轮 cu1 对照。另:GUI 体积相对旧基线 +# 涨了 12.9%(13.92 → 15.72 MiB),其中「代码增长」与「依赖 cu16」也没分离。 # **只调优化强度**:panic 与 strip 绝不写进这里。那两项改变的是整个二进制的运行时行为 # (panic 策略决定能否 unwind 出栈、strip 决定符号表留不留),不是「给依赖放宽」的范畴。 [profile.release.package."*"] opt-level = "z" codegen-units = 16 -# 快档的依赖覆盖单独写一遍:package 覆盖是按 profile 分别生效的(`[profile.release.package."*"]` -# 只作用在 release 档),显式写出来就不必赌 `inherits` 会不会连 package 覆盖一起继承。 -# 值与 fast 档自身一致——依赖编得快是快档的目的,不是再抬一档优化强度。 +# `inherits = "release"` 会把 `[profile.release.package."*"]` **一起继承过来**(实测:删掉下面这块, +# fast 档的外部依赖就从 opt-level 2 退回 `"z"`;workspace 成员不受 `*` 覆盖、仍是 fast 自己的 2)。 +# 所以这块**必须存在**,它是承重墙不是冗余兜底 —— 删掉会让 fast 档的依赖静默退回 `"z"`。 [profile.fast.package."*"] opt-level = 2 codegen-units = 16 diff --git a/packaging/README.md b/packaging/README.md index cb84ab9..2469991 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -202,24 +202,25 @@ SLINT_BACKEND=winit-software unlucky-launcher # 环境变量(Slint | `release.package."*"` | 同上,**只作用于依赖** | `"z"` | 不可覆盖 | 16 | 继承 | | `fast` | 日常迭代、本机跑测试 | 2 | `thin` | 16 | `unwind` | -- **`release` 是体积档**:`fat` + 单 CGU 换来实测 GUI −10.8% / CLI −18.7%(§7.1)。变慢的根源在 - `codegen-units = 1`(整个 crate 只切一个 CGU,LTO 也只有一个线程可跑;`fat` 只管"跨 crate 全量参与", - 不等于单线程),375 个 crate 排队链接就是十几分钟的来源。 +- **`release` 是体积档**:`fat` + 单 CGU 换来实测 GUI −10.8% / CLI −18.7%(§7.1)。变慢的根源在 `codegen-units = 1` + (单 CGU → LTO 只一个线程可跑;`fat` 只管"跨 crate 全量参与",不等于单线程),375 个 crate 排队链接就是十几分钟的量。 - **`release.package."*"` 放宽的只有并行度,不是 opt-level**:实测把依赖 opt-level 抬到 3 反而**又慢 29.6% 又大 19~24%**(§7.1),所以保持 `"z"`、只把 `codegen-units` 放到 16。package 覆盖**只允许调优化强度**: `panic` / `lto` / `rpath` 写进去 cargo 直接报错,`strip` 会改变整个二进制的运行时行为——都不许出现。 - **`fast` 是速度档,不是发布物**:`thin` LTO + 16 CGU 可并行,`opt-level = 2` 介于 `z` 与 3 之间。 - 必须显式 `panic = "unwind"` ——`release` 是 `abort`,`inherits` 会照抄,漏了这一行 - `cargo test --profile fast` 连编译都过不去(test harness 依赖 unwind)。**但它在机械盘机器上冷编译 - 并无收益**(比 release 还慢、体积 2.3 倍,§7.1),价值在 SSD 机器与增量重编。 + `panic = "unwind"` 是给**编出来的二进制**留的(`release` 是 `abort`,`inherits` 会照抄);`cargo test` + **不**依赖它——cargo 对 test 目标自己强制 unwind(实测 release/abort 档下 `cargo test --profile release` + 照跑、23 个测试全过,test 单元的 rustc 参数里没有 `-Cpanic=`)。要看这行是否生效,比 `cargo build -v` + 的 rustc 参数:release 有 `panic=abort`、fast 没有。它继承 `strip="symbols"`,所以能 unwind 但**没有符号 + 回溯**——要栈回溯就给 fast 档加 `strip = false`,代价是体积再涨。 +- **`fast` 在机械盘机器上冷编译并无收益**(比 release 还慢、体积 2.3 倍,§7.1),价值在 SSD 机器与增量重编。 +- **`[profile.fast.package."*"]` 是承重墙**:`inherits` 会把 release 的 package 覆盖一起带过来(实测:删掉它,fast 档外部依赖静默退回 `"z"`),必须存在。 - 本地开发迭代走 `cargo build`(dev profile)不受影响,但 **`ci.yml` 每次 push/PR 都跑 - `cargo build --workspace --release`**,会实打实吃这份 fat LTO 的链接时间——CI 慢的一部分是 release - 档构建,不是测试本身。`panic = "abort"` 意味着 panic 不带 backtrace 栈展开——UI 层已用 `Result` 承接错误,可接受。 + `cargo build --workspace --release`**,会实打实吃这份 fat LTO 的链接时间——CI 慢的一部分是 release 档构建。 ## 7. 实测(本机,不是估算) -构建环境:rustc 1.99.1 stable(host `x86_64-pc-windows-gnu`,MinGW 链接器)。§7.2/§7.3 的早数字是在 -同一刻另有 worker 做全量 debug 构建(偏悲观的真实负载)时测的,§7.1 的 M96 两行是空载冷编译。 +构建环境:rustc 1.99.1 stable / `x86_64-pc-windows-gnu`(MinGW 链接器)。§7.2/§7.3 的早数字是另有 worker 并发做全量 debug 构建时测的(偏悲观);§7.1 的三行 M96 数据是空载冷编译。 ### 7.1 体积与冷构建耗时(实测字节数,不是估算) @@ -231,13 +232,12 @@ SLINT_BACKEND=winit-software unlucky-launcher # 环境变量(Slint | `release`,`fat` + 依赖 `"z"` / cu16(**M96 起,发布档**) | **16,479,232 B = 15.72 MiB** | **13,910,528 B = 13.27 MiB** | **6,256,128 B = 5.97 MiB** | **16m01s(冷)** | | `fast`,`thin` + cu16(M96 起,日常档) | 38,182,400 B = 36.41 MiB | 33,570,304 B = 32.02 MiB | 15,967,744 B = 15.23 MiB | 24m27s(冷) | -测量条件(M96 三行):12 核 / `x86_64-pc-windows-gnu`,`-j 4`,源码在机械盘、`CARGO_TARGET_DIR` 在 SSD,均为**删空 target -后的冷编译**、同机同晚无并发负载;M46 两行是更早提交上的数字(依赖已热 / 另有并发),**跨行比耗时没意义**,体积差 -也不能全归给 profile(其间多了 iced / presenter / i18n 等 crate)。 -两条结论都反直觉但都是实测:① **依赖 opt-level 从 3 退回 `"z"` 又快 29.6% 又小 19~24%**——收益全在 `codegen-units = 16` 的 -并行 codegen,抬 opt-level 是拿编译时间和体积换运行期;② `fast` **冷编译比 `release` 还慢**(24m27s vs 16m01s)、体积 2.3 倍, -瓶颈在两个大 UI crate + 链接 + 机械盘 IO——它的定位是 **SSD 机器与增量重编**(thin 不必每次全程序 LTO),不是冷编译加速。 -体积构成(按依赖树判断):Slint 运行时(femtovg + software 双渲染器 + winit/accesskit/托盘)+ rustls/reqwest + rig/rmcp/axum 是主要来源;`ull` 更小是 D18 纪律(CLI 零 UI 依赖)。 +测量条件(M96 三行):12 核 / `x86_64-pc-windows-gnu` / `-j 4`,源码机械盘、`CARGO_TARGET_DIR` 在 SSD,均为**删空 target 后的 +冷编译**、同机同晚无并发负载;M46 两行是更早提交上的数字(依赖已热 / 另有并发),**跨行比耗时没意义**。 +① **依赖 opt-level 从 3 退回 `"z"` 又快 29.6% 又小 19~24%**(两臂同为 cu16,唯一自变量是 opt-level)——抬 opt-level 是拿编译时间和体积换运行期; +`cu1 → cu16` 的收益本轮**没有同条件对照**,未归因。② `fast` **冷编译比 `release` 还慢**(24m27s vs 16m01s)、体积 2.3 倍,瓶颈在两个大 UI +crate + 链接 + 机械盘 IO——定位是 **SSD 机器与增量重编**,不是冷编译加速。体积归因:GUI 相对旧基线 +12.9%(13.92 → 15.72 MiB)里 +「代码增长」与「依赖 cu16」**未分离**;`ull` 只 +1.7%,在 +1~3% 口径内。体积构成:Slint 运行时(双渲染器 + winit/accesskit/托盘)+ rustls/reqwest + rig/rmcp/axum 为主,`ull` 更小是 D18(CLI 零 UI 依赖)的结果。 ### 7.2 冒烟(真跑,2026-10-31 夜间 + 11-01 早,本机 Win11 26100)